mirror of
https://github.com/netbox-community/netbox.git
synced 2026-04-16 05:59:55 +02:00
Compare commits
13 Commits
post-raw-s
...
21893-perm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d76eb887b | ||
|
|
1af320e0a9 | ||
|
|
c28736e1d6 | ||
|
|
f0fc93d827 | ||
|
|
bf9de4721e | ||
|
|
bce667300a | ||
|
|
660ca42149 | ||
|
|
75e1b86613 | ||
|
|
e12334c01b | ||
|
|
5aeb045fb5 | ||
|
|
6c12d8b402 | ||
|
|
9b734bac93 | ||
|
|
0f277894b2 |
@@ -15,7 +15,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.5.7
|
||||
placeholder: v4.5.8
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
@@ -27,7 +27,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox Version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.5.7
|
||||
placeholder: v4.5.8
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/03-performance.yaml
vendored
2
.github/ISSUE_TEMPLATE/03-performance.yaml
vendored
@@ -8,7 +8,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox Version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.5.7
|
||||
placeholder: v4.5.8
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
||||
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -56,9 +56,9 @@ jobs:
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- name: Check Python linting & PEP8 compliance
|
||||
uses: astral-sh/ruff-action@4919ec5cf1f49eff0871dbcea0da843445b837e6 # v3.6.1
|
||||
uses: astral-sh/ruff-action@0ce1b0bf8b818ef400413f810f8a11cdbda0034b # v4.0.0
|
||||
with:
|
||||
version: "0.15.2"
|
||||
version: "0.15.10"
|
||||
args: "check --output-format=github"
|
||||
src: "netbox/"
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Create app token
|
||||
uses: actions/create-github-app-token@v1
|
||||
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: 1076524
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
run: python netbox/manage.py makemessages -l ${{ env.LOCALE }}
|
||||
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
|
||||
uses: EndBug/add-and-commit@290ea2c423ad77ca9c62ae0f5b224379612c0321 # v10.0.0
|
||||
with:
|
||||
add: 'netbox/translations/'
|
||||
default_author: github_actions
|
||||
|
||||
@@ -55,7 +55,8 @@ django-storages
|
||||
|
||||
# Abstraction models for rendering and paginating HTML tables
|
||||
# https://github.com/jieter/django-tables2/blob/master/CHANGELOG.md
|
||||
django-tables2
|
||||
# See #21902 for upgrading to django-tables2 v2.9+
|
||||
django-tables2<2.9
|
||||
|
||||
# User-defined tags for objects
|
||||
# https://github.com/jazzband/django-taggit/blob/master/CHANGELOG.rst
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"openapi": "3.0.3",
|
||||
"info": {
|
||||
"title": "NetBox REST API",
|
||||
"version": "4.5.7",
|
||||
"version": "4.5.8",
|
||||
"license": {
|
||||
"name": "Apache v2 License"
|
||||
}
|
||||
@@ -57744,7 +57744,7 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"explode": true,
|
||||
@@ -57757,7 +57757,7 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"explode": true,
|
||||
@@ -57770,7 +57770,7 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"explode": true,
|
||||
@@ -57783,7 +57783,7 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"explode": true,
|
||||
@@ -57796,7 +57796,7 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"explode": true,
|
||||
@@ -57809,7 +57809,7 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"explode": true,
|
||||
@@ -57822,7 +57822,7 @@
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
"format": "int64"
|
||||
}
|
||||
},
|
||||
"explode": true,
|
||||
@@ -240094,8 +240094,9 @@
|
||||
},
|
||||
"speed": {
|
||||
"type": "integer",
|
||||
"maximum": 2147483647,
|
||||
"maximum": 9223372036854775807,
|
||||
"minimum": 0,
|
||||
"format": "int64",
|
||||
"nullable": true,
|
||||
"title": "Speed (Kbps)"
|
||||
},
|
||||
@@ -241179,8 +241180,9 @@
|
||||
},
|
||||
"speed": {
|
||||
"type": "integer",
|
||||
"maximum": 2147483647,
|
||||
"maximum": 9223372036854775807,
|
||||
"minimum": 0,
|
||||
"format": "int64",
|
||||
"nullable": true,
|
||||
"title": "Speed (Kbps)"
|
||||
},
|
||||
@@ -258026,8 +258028,9 @@
|
||||
},
|
||||
"speed": {
|
||||
"type": "integer",
|
||||
"maximum": 2147483647,
|
||||
"maximum": 9223372036854775807,
|
||||
"minimum": 0,
|
||||
"format": "int64",
|
||||
"nullable": true,
|
||||
"title": "Speed (Kbps)"
|
||||
},
|
||||
@@ -280622,8 +280625,9 @@
|
||||
},
|
||||
"speed": {
|
||||
"type": "integer",
|
||||
"maximum": 2147483647,
|
||||
"maximum": 9223372036854775807,
|
||||
"minimum": 0,
|
||||
"format": "int64",
|
||||
"nullable": true,
|
||||
"title": "Speed (Kbps)"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
# NetBox v4.5
|
||||
|
||||
## v4.5.8 (2026-04-14)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* [#21430](https://github.com/netbox-community/netbox/issues/21430) - Display the device role's color in the device view
|
||||
* [#21795](https://github.com/netbox-community/netbox/issues/21795) - Update `humanize_speed` template filter to support decimal Gbps/Tbps values
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [#21529](https://github.com/netbox-community/netbox/issues/21529) - Exclude non-existent custom fields from object changelog data returned via the REST API
|
||||
* [#21542](https://github.com/netbox-community/netbox/issues/21542) - Expand interface speed field to 64-bit integer to prevent overflow for LAG interfaces exceeding ~2.1 Tbps
|
||||
* [#21704](https://github.com/netbox-community/netbox/issues/21704) - Fix missing port mappings in device type YAML export
|
||||
* [#21783](https://github.com/netbox-community/netbox/issues/21783) - Fix support for bulk import of cables connected to power feeds
|
||||
* [#21801](https://github.com/netbox-community/netbox/issues/21801) - Prevent duplicate filename collision when uploading files using S3 storage
|
||||
* [#21814](https://github.com/netbox-community/netbox/issues/21814) - Fix custom script "last run" time to reflect job start time rather than creation time
|
||||
* [#21835](https://github.com/netbox-community/netbox/issues/21835) - Correct help text for color selection form fields
|
||||
* [#21841](https://github.com/netbox-community/netbox/issues/21841) - Restore visibility of the edit button for script modules to non-superusers
|
||||
* [#21845](https://github.com/netbox-community/netbox/issues/21845) - Fix CSV export of connection columns rendering template whitespace instead of a formatted value
|
||||
* [#21869](https://github.com/netbox-community/netbox/issues/21869) - Remove redundant `ScriptModule` class synchronization triggered on save
|
||||
|
||||
---
|
||||
|
||||
## v4.5.7 (2026-04-03)
|
||||
|
||||
### Enhancements
|
||||
|
||||
@@ -18,7 +18,7 @@ class JobTableTest(TableTestCases.StandardTableTestCase):
|
||||
class ObjectChangeTableTest(TableTestCases.StandardTableTestCase):
|
||||
table = ObjectChangeTable
|
||||
queryset_sources = [
|
||||
('ObjectChangeListView', ObjectChange.objects.valid_models()),
|
||||
('ObjectChangeListView', ObjectChange.objects.all()),
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -192,6 +192,12 @@ class DataFileView(generic.ObjectView):
|
||||
layout.Column(
|
||||
panels.DataFilePanel(),
|
||||
panels.DataFileContentPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -253,6 +259,12 @@ class JobLogView(generic.ObjectView):
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
ContextTablePanel('table', title=_('Log Entries')),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -393,6 +405,12 @@ class ConfigRevisionView(generic.ObjectView):
|
||||
layout.Column(
|
||||
TemplatePanel('core/panels/configrevision_data.html'),
|
||||
TemplatePanel('core/panels/configrevision_comment.html'),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1409,8 +1409,16 @@ class CableImportForm(PrimaryModelImportForm):
|
||||
side_a_device = CSVModelChoiceField(
|
||||
label=_('Side A device'),
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text=_('Device name')
|
||||
help_text=_('Device name (for device component terminations)')
|
||||
)
|
||||
side_a_power_panel = CSVModelChoiceField(
|
||||
label=_('Side A power panel'),
|
||||
queryset=PowerPanel.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text=_('Power panel name (for power feed terminations)')
|
||||
)
|
||||
side_a_type = CSVContentTypeField(
|
||||
label=_('Side A type'),
|
||||
@@ -1434,8 +1442,16 @@ class CableImportForm(PrimaryModelImportForm):
|
||||
side_b_device = CSVModelChoiceField(
|
||||
label=_('Side B device'),
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text=_('Device name')
|
||||
help_text=_('Device name (for device component terminations)')
|
||||
)
|
||||
side_b_power_panel = CSVModelChoiceField(
|
||||
label=_('Side B power panel'),
|
||||
queryset=PowerPanel.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text=_('Power panel name (for power feed terminations)')
|
||||
)
|
||||
side_b_type = CSVContentTypeField(
|
||||
label=_('Side B type'),
|
||||
@@ -1490,8 +1506,9 @@ class CableImportForm(PrimaryModelImportForm):
|
||||
class Meta:
|
||||
model = Cable
|
||||
fields = [
|
||||
'side_a_site', 'side_a_device', 'side_a_type', 'side_a_name', 'side_b_site', 'side_b_device', 'side_b_type',
|
||||
'side_b_name', 'type', 'status', 'profile', 'tenant', 'label', 'color', 'length', 'length_unit',
|
||||
'side_a_site', 'side_a_device', 'side_a_power_panel', 'side_a_type', 'side_a_name',
|
||||
'side_b_site', 'side_b_device', 'side_b_power_panel', 'side_b_type', 'side_b_name',
|
||||
'type', 'status', 'profile', 'tenant', 'label', 'color', 'length', 'length_unit',
|
||||
'description', 'owner', 'comments', 'tags',
|
||||
]
|
||||
|
||||
@@ -1501,16 +1518,22 @@ class CableImportForm(PrimaryModelImportForm):
|
||||
if data:
|
||||
# Limit choices for side_a_device to the assigned side_a_site
|
||||
if side_a_site := data.get('side_a_site'):
|
||||
side_a_device_params = {f'site__{self.fields["side_a_site"].to_field_name}': side_a_site}
|
||||
side_a_parent_params = {f'site__{self.fields['side_a_site'].to_field_name}': side_a_site}
|
||||
self.fields['side_a_device'].queryset = self.fields['side_a_device'].queryset.filter(
|
||||
**side_a_device_params
|
||||
**side_a_parent_params
|
||||
)
|
||||
self.fields['side_a_power_panel'].queryset = self.fields['side_a_power_panel'].queryset.filter(
|
||||
**side_a_parent_params
|
||||
)
|
||||
|
||||
# Limit choices for side_b_device to the assigned side_b_site
|
||||
if side_b_site := data.get('side_b_site'):
|
||||
side_b_device_params = {f'site__{self.fields["side_b_site"].to_field_name}': side_b_site}
|
||||
side_b_parent_params = {f'site__{self.fields['side_b_site'].to_field_name}': side_b_site}
|
||||
self.fields['side_b_device'].queryset = self.fields['side_b_device'].queryset.filter(
|
||||
**side_b_device_params
|
||||
**side_b_parent_params
|
||||
)
|
||||
self.fields['side_b_power_panel'].queryset = self.fields['side_b_power_panel'].queryset.filter(
|
||||
**side_b_parent_params
|
||||
)
|
||||
|
||||
def _clean_side(self, side):
|
||||
@@ -1522,33 +1545,57 @@ class CableImportForm(PrimaryModelImportForm):
|
||||
assert side in 'ab', f"Invalid side designation: {side}"
|
||||
|
||||
device = self.cleaned_data.get(f'side_{side}_device')
|
||||
power_panel = self.cleaned_data.get(f'side_{side}_power_panel')
|
||||
content_type = self.cleaned_data.get(f'side_{side}_type')
|
||||
name = self.cleaned_data.get(f'side_{side}_name')
|
||||
if not device or not content_type or not name:
|
||||
if not content_type or not name:
|
||||
return None
|
||||
|
||||
model = content_type.model_class()
|
||||
try:
|
||||
if (
|
||||
device.virtual_chassis and
|
||||
device.virtual_chassis.master == device and
|
||||
not model.objects.filter(device=device, name=name).exists()
|
||||
):
|
||||
termination_object = model.objects.get(device__in=device.virtual_chassis.members.all(), name=name)
|
||||
else:
|
||||
termination_object = model.objects.get(device=device, name=name)
|
||||
if termination_object.cable is not None and termination_object.cable != self.instance:
|
||||
|
||||
# PowerFeed terminations reference a PowerPanel, not a Device
|
||||
if content_type.model == 'powerfeed':
|
||||
if not power_panel:
|
||||
return None
|
||||
try:
|
||||
termination_object = model.objects.get(power_panel=power_panel, name=name)
|
||||
if termination_object.cable is not None and termination_object.cable != self.instance:
|
||||
raise forms.ValidationError(
|
||||
_("Side {side_upper}: {power_panel} {termination_object} is already connected").format(
|
||||
side_upper=side.upper(), power_panel=power_panel, termination_object=termination_object
|
||||
)
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise forms.ValidationError(
|
||||
_("Side {side_upper}: {device} {termination_object} is already connected").format(
|
||||
side_upper=side.upper(), device=device, termination_object=termination_object
|
||||
_("{side_upper} side termination not found: {power_panel} {name}").format(
|
||||
side_upper=side.upper(), power_panel=power_panel, name=name
|
||||
)
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise forms.ValidationError(
|
||||
_("{side_upper} side termination not found: {device} {name}").format(
|
||||
side_upper=side.upper(), device=device, name=name
|
||||
else:
|
||||
if not device:
|
||||
return None
|
||||
try:
|
||||
if (
|
||||
device.virtual_chassis and
|
||||
device.virtual_chassis.master == device and
|
||||
not model.objects.filter(device=device, name=name).exists()
|
||||
):
|
||||
termination_object = model.objects.get(device__in=device.virtual_chassis.members.all(), name=name)
|
||||
else:
|
||||
termination_object = model.objects.get(device=device, name=name)
|
||||
if termination_object.cable is not None and termination_object.cable != self.instance:
|
||||
raise forms.ValidationError(
|
||||
_("Side {side_upper}: {device} {termination_object} is already connected").format(
|
||||
side_upper=side.upper(), device=device, termination_object=termination_object
|
||||
)
|
||||
)
|
||||
except ObjectDoesNotExist:
|
||||
raise forms.ValidationError(
|
||||
_("{side_upper} side termination not found: {device} {name}").format(
|
||||
side_upper=side.upper(), device=device, name=name
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
setattr(self.instance, f'{side}_terminations', [termination_object])
|
||||
return termination_object
|
||||
|
||||
|
||||
@@ -150,9 +150,25 @@ class PortTemplateMappingImportForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = PortTemplateMapping
|
||||
fields = [
|
||||
'front_port', 'front_port_position', 'rear_port', 'rear_port_position',
|
||||
'device_type', 'module_type', 'front_port', 'front_port_position', 'rear_port', 'rear_port_position',
|
||||
]
|
||||
|
||||
def clean_device_type(self):
|
||||
if device_type := self.cleaned_data['device_type']:
|
||||
front_port = self.fields['front_port']
|
||||
rear_port = self.fields['rear_port']
|
||||
front_port.queryset = front_port.queryset.filter(device_type=device_type)
|
||||
rear_port.queryset = rear_port.queryset.filter(device_type=device_type)
|
||||
return device_type
|
||||
|
||||
def clean_module_type(self):
|
||||
if module_type := self.cleaned_data['module_type']:
|
||||
front_port = self.fields['front_port']
|
||||
rear_port = self.fields['rear_port']
|
||||
front_port.queryset = front_port.queryset.filter(module_type=module_type)
|
||||
rear_port.queryset = rear_port.queryset.filter(module_type=module_type)
|
||||
return module_type
|
||||
|
||||
|
||||
class ModuleBayTemplateImportForm(forms.ModelForm):
|
||||
|
||||
|
||||
@@ -166,20 +166,6 @@ def retrace_cable_paths(instance, **kwargs):
|
||||
cablepath.retrace()
|
||||
|
||||
|
||||
@receiver(post_save, sender=Cable)
|
||||
def retrace_cable_paths_on_raw_create(sender, instance, raw=False, **kwargs):
|
||||
"""
|
||||
Trigger cable path retracing for a Cable instance when dependencies need to be
|
||||
recalculated. Callers should fire post_save with post_raw_create=True after
|
||||
all CableTerminations are in place.
|
||||
"""
|
||||
post_raw_create = kwargs.get('post_raw_create', False)
|
||||
if not post_raw_create:
|
||||
return
|
||||
instance._terminations_modified = True
|
||||
trace_paths.send(Cable, instance=instance, created=True)
|
||||
|
||||
|
||||
@receiver((post_delete, post_save), sender=PortMapping)
|
||||
def update_passthrough_port_paths(instance, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -194,6 +194,28 @@ class SiteTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
||||
'description': 'New description',
|
||||
}
|
||||
|
||||
def test_get_object_with_only_site_view_permission_hides_unauthorized_embedded_panels(self):
|
||||
site = self._get_queryset().first()
|
||||
|
||||
obj_perm = ObjectPermission(
|
||||
name='Test permission',
|
||||
actions=['view'],
|
||||
)
|
||||
obj_perm.save()
|
||||
obj_perm.users.add(self.user)
|
||||
obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
|
||||
|
||||
response = self.client.get(site.get_absolute_url())
|
||||
self.assertHttpStatus(response, 200)
|
||||
|
||||
for panel, url in (
|
||||
('locations', reverse('dcim:location_list')),
|
||||
('devices', reverse('dcim:device_list')),
|
||||
('image attachments', reverse('extras:imageattachment_list')),
|
||||
):
|
||||
with self.subTest(panel=panel):
|
||||
self.assertNotContains(response, url)
|
||||
|
||||
|
||||
class LocationTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
model = Location
|
||||
@@ -3603,6 +3625,21 @@ class CableTestCase(
|
||||
cable3 = Cable(a_terminations=[interfaces[2]], b_terminations=[interfaces[5]], type=CableTypeChoices.TYPE_CAT6)
|
||||
cable3.save()
|
||||
|
||||
# Power panel, power feeds, and power ports for powerfeed-to-powerport cable import tests
|
||||
power_panel = PowerPanel.objects.create(site=sites[0], name='Power Panel 1')
|
||||
power_feeds = (
|
||||
PowerFeed(name='Power Feed 1', power_panel=power_panel),
|
||||
PowerFeed(name='Power Feed 2', power_panel=power_panel),
|
||||
PowerFeed(name='Power Feed 3', power_panel=power_panel),
|
||||
)
|
||||
PowerFeed.objects.bulk_create(power_feeds)
|
||||
power_ports = (
|
||||
PowerPort(device=devices[3], name='Power Port 1'),
|
||||
PowerPort(device=devices[3], name='Power Port 2'),
|
||||
PowerPort(device=devices[3], name='Power Port 3'),
|
||||
)
|
||||
PowerPort.objects.bulk_create(power_ports)
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
@@ -3640,7 +3677,14 @@ class CableTestCase(
|
||||
"Site 1,Device 3,dcim.interface,Interface 3,Site 2,Device 1,dcim.interface,Interface 3",
|
||||
"Site 1,Device 1,dcim.interface,Device 2 Interface,Site 2,Device 1,dcim.interface,Interface 4",
|
||||
"Site 1,Device 1,dcim.interface,Device 3 Interface,Site 2,Device 1,dcim.interface,Interface 5",
|
||||
)
|
||||
),
|
||||
'powerfeed-to-powerport': (
|
||||
# Ensure that powerfeed-to-powerport cables can be imported via CSV using side_a_power_panel
|
||||
"side_a_power_panel,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name",
|
||||
"Power Panel 1,dcim.powerfeed,Power Feed 1,Device 4,dcim.powerport,Power Port 1",
|
||||
"Power Panel 1,dcim.powerfeed,Power Feed 2,Device 4,dcim.powerport,Power Port 2",
|
||||
"Power Panel 1,dcim.powerfeed,Power Feed 3,Device 4,dcim.powerport,Power Port 3",
|
||||
),
|
||||
}
|
||||
|
||||
cls.csv_update_data = (
|
||||
|
||||
@@ -9,6 +9,7 @@ from rest_framework import serializers
|
||||
from core.api.serializers_.jobs import JobSerializer
|
||||
from core.choices import ManagedFileRootPathChoices
|
||||
from extras.models import Script, ScriptModule
|
||||
from extras.utils import validate_script_content
|
||||
from netbox.api.serializers import ValidatedModelSerializer
|
||||
from utilities.datetime import local_now
|
||||
|
||||
@@ -39,6 +40,15 @@ class ScriptModuleSerializer(ValidatedModelSerializer):
|
||||
data = super().validate(data)
|
||||
data.pop('file_root', None)
|
||||
if file is not None:
|
||||
# Validate that the uploaded script can be loaded as a Python module
|
||||
content = file.read()
|
||||
file.seek(0)
|
||||
try:
|
||||
validate_script_content(content, file.name)
|
||||
except Exception as e:
|
||||
raise serializers.ValidationError(
|
||||
_("Error loading script: {error}").format(error=e)
|
||||
)
|
||||
data['file'] = file
|
||||
return data
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from core.choices import JobIntervalChoices
|
||||
from core.forms import ManagedFileForm
|
||||
from extras.utils import validate_script_content
|
||||
from utilities.datetime import local_now
|
||||
from utilities.forms.widgets import DateTimePicker, NumberWithOptions
|
||||
|
||||
@@ -64,6 +65,22 @@ class ScriptFileForm(ManagedFileForm):
|
||||
"""
|
||||
ManagedFileForm with a custom save method to use django-storages.
|
||||
"""
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
if upload_file := self.cleaned_data.get('upload_file'):
|
||||
# Validate that the uploaded script can be loaded as a Python module
|
||||
content = upload_file.read()
|
||||
upload_file.seek(0)
|
||||
try:
|
||||
validate_script_content(content, upload_file.name)
|
||||
except Exception as e:
|
||||
raise forms.ValidationError(
|
||||
_("Error loading script: {error}").format(error=e)
|
||||
)
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# If a file was uploaded, save it to disk
|
||||
if self.cleaned_data['upload_file']:
|
||||
|
||||
@@ -5,8 +5,6 @@ from functools import cached_property
|
||||
from django.contrib.contenttypes.fields import GenericRelation
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from django.db.models.signals import post_save
|
||||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
@@ -188,9 +186,7 @@ class ScriptModule(PythonModuleMixin, JobsMixin, ManagedFile):
|
||||
def save(self, *args, **kwargs):
|
||||
self.file_root = ManagedFileRootPathChoices.SCRIPTS
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
# Sync script classes after the module has been saved. This is the
|
||||
# single intended synchronization path for ScriptModule saves.
|
||||
self.sync_classes()
|
||||
|
||||
|
||||
@receiver(post_save, sender=ScriptModule)
|
||||
def script_module_post_save_handler(instance, created, **kwargs):
|
||||
instance.sync_classes()
|
||||
|
||||
@@ -1450,6 +1450,21 @@ class ScriptModuleTest(APITestCase):
|
||||
self.assertTrue(ScriptModule.objects.filter(file_path='test_upload.py').exists())
|
||||
self.assertTrue(Script.objects.filter(module__file_path='test_upload.py', name='TestScript').exists())
|
||||
|
||||
def test_upload_faulty_script_module(self):
|
||||
"""Uploading a script with an import error should return 400 and not create a DB record."""
|
||||
self.add_permissions('extras.add_scriptmodule', 'core.add_managedfile')
|
||||
# 'extras.script' is invalid; the correct module is 'extras.scripts'
|
||||
script_content = b"from extras.script import Script\nclass TestScript(Script):\n pass\n"
|
||||
upload_file = SimpleUploadedFile('test_faulty.py', script_content, content_type='text/plain')
|
||||
response = self.client.post(
|
||||
self.url,
|
||||
{'file': upload_file},
|
||||
format='multipart',
|
||||
**self.header,
|
||||
)
|
||||
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
|
||||
self.assertFalse(ScriptModule.objects.filter(file_path='test_faulty.py').exists())
|
||||
|
||||
def test_upload_script_module_without_file_fails(self):
|
||||
self.add_permissions('extras.add_scriptmodule', 'core.add_managedfile')
|
||||
response = self.client.post(self.url, {}, format='json', **self.header)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import importlib
|
||||
import types
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured, SuspiciousFileOperation
|
||||
@@ -21,6 +22,7 @@ __all__ = (
|
||||
'is_script',
|
||||
'is_taggable',
|
||||
'run_validators',
|
||||
'validate_script_content',
|
||||
)
|
||||
|
||||
|
||||
@@ -134,6 +136,17 @@ def is_script(obj):
|
||||
return False
|
||||
|
||||
|
||||
def validate_script_content(content, filename):
|
||||
"""
|
||||
Validate that the given content can be loaded as a Python module by compiling
|
||||
and executing it. Raises an exception if the script cannot be loaded.
|
||||
"""
|
||||
code = compile(content, filename, 'exec')
|
||||
module_name = Path(filename).stem
|
||||
module = types.ModuleType(module_name)
|
||||
exec(code, module.__dict__)
|
||||
|
||||
|
||||
def is_report(obj):
|
||||
"""
|
||||
Returns True if the given object is a Report.
|
||||
|
||||
@@ -16,6 +16,7 @@ from netbox.ui.panels import (
|
||||
CommentsPanel,
|
||||
ContextTablePanel,
|
||||
ObjectsTablePanel,
|
||||
PluginContentPanel,
|
||||
RelatedObjectsPanel,
|
||||
TemplatePanel,
|
||||
)
|
||||
@@ -55,11 +56,13 @@ class VRFView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
layout.Column(
|
||||
panels.VRFPanel(),
|
||||
TagsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
layout.Column(
|
||||
RelatedObjectsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
@@ -70,6 +73,11 @@ class VRFView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
ContextTablePanel('export_targets_table', title=_('Export route targets')),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@@ -169,10 +177,12 @@ class RouteTargetView(generic.ObjectView):
|
||||
layout.Column(
|
||||
panels.RouteTargetPanel(),
|
||||
TagsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
layout.Column(
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
@@ -207,6 +217,11 @@ class RouteTargetView(generic.ObjectView):
|
||||
),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ from netbox.graphql.types import (
|
||||
PrimaryObjectType,
|
||||
)
|
||||
from netbox.models import NestedGroupModel, NetBoxModel, OrganizationalModel, PrimaryModel
|
||||
from netbox.registry import registry
|
||||
from netbox.tables import (
|
||||
NestedGroupModelTable,
|
||||
NetBoxTable,
|
||||
@@ -174,11 +175,10 @@ class FilterSetClassesTestCase(TestCase):
|
||||
@staticmethod
|
||||
def get_filterset_for_model(model):
|
||||
"""
|
||||
Import and return the filterset class for a given model.
|
||||
Return the filterset class for a given model from the application registry.
|
||||
"""
|
||||
app_label = model._meta.app_label
|
||||
model_name = model.__name__
|
||||
return import_string(f'{app_label}.filtersets.{model_name}FilterSet')
|
||||
label = f'{model._meta.app_label}.{model._meta.model_name}'
|
||||
return registry['filtersets'].get(label)
|
||||
|
||||
@staticmethod
|
||||
def get_model_filterset_base_class(model):
|
||||
@@ -204,6 +204,7 @@ class FilterSetClassesTestCase(TestCase):
|
||||
for model in apps.get_models():
|
||||
if base_class := self.get_model_filterset_base_class(model):
|
||||
filterset = self.get_filterset_for_model(model)
|
||||
self.assertIsNotNone(filterset, f"No registered filterset found for model {model}")
|
||||
self.assertTrue(
|
||||
issubclass(filterset, base_class),
|
||||
f"{filterset} does not inherit from {base_class}",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.test import TestCase
|
||||
from django.test import RequestFactory, TestCase
|
||||
|
||||
from circuits.choices import CircuitStatusChoices, VirtualCircuitTerminationRoleChoices
|
||||
from circuits.models import (
|
||||
@@ -8,9 +8,12 @@ from circuits.models import (
|
||||
VirtualCircuitTermination,
|
||||
VirtualCircuitType,
|
||||
)
|
||||
from core.models import ObjectType
|
||||
from dcim.choices import InterfaceTypeChoices
|
||||
from dcim.models import Interface
|
||||
from dcim.models import Interface, Site
|
||||
from netbox.ui import attrs
|
||||
from netbox.ui.panels import ObjectsTablePanel
|
||||
from users.models import ObjectPermission, User
|
||||
from utilities.testing import create_test_device
|
||||
from vpn.choices import (
|
||||
AuthenticationAlgorithmChoices,
|
||||
@@ -213,3 +216,55 @@ class RelatedObjectListAttrTest(TestCase):
|
||||
self.assertInHTML('<li>IKE Proposal 2</li>', rendered)
|
||||
self.assertNotIn('IKE Proposal 3', rendered)
|
||||
self.assertIn('…', rendered)
|
||||
|
||||
|
||||
class ObjectsTablePanelTest(TestCase):
|
||||
"""
|
||||
Verify that ObjectsTablePanel.should_render() hides the panel when
|
||||
the requesting user lacks view permission for the panel's model.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.user = User.objects.create_user(username='test_user', password='test_password')
|
||||
|
||||
# Grant view permission only for Site
|
||||
obj_perm = ObjectPermission.objects.create(
|
||||
name='View sites only',
|
||||
actions=['view'],
|
||||
)
|
||||
obj_perm.object_types.add(ObjectType.objects.get_for_model(Site))
|
||||
obj_perm.users.add(cls.user)
|
||||
|
||||
def setUp(self):
|
||||
self.factory = RequestFactory()
|
||||
self.panel = ObjectsTablePanel(model='dcim.site')
|
||||
self.panel_no_perm = ObjectsTablePanel(model='dcim.location')
|
||||
|
||||
def _make_context(self, user=None):
|
||||
if user is None:
|
||||
return {}
|
||||
request = self.factory.get('/')
|
||||
request.user = user
|
||||
return {'request': request}
|
||||
|
||||
def test_should_render_without_request(self):
|
||||
"""
|
||||
Panel should render when no request is present in context.
|
||||
"""
|
||||
context = self.panel.get_context({})
|
||||
self.assertTrue(self.panel.should_render(context))
|
||||
|
||||
def test_should_render_with_permission(self):
|
||||
"""
|
||||
Panel should render when the user has view permission for the panel's model.
|
||||
"""
|
||||
context = self.panel.get_context(self._make_context(self.user))
|
||||
self.assertTrue(self.panel.should_render(context))
|
||||
|
||||
def test_should_not_render_without_permission(self):
|
||||
"""
|
||||
Panel should be hidden when the user lacks view permission for the panel's model.
|
||||
"""
|
||||
context = self.panel_no_perm.get_context(self._make_context(self.user))
|
||||
self.assertFalse(self.panel_no_perm.should_render(context))
|
||||
|
||||
@@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from netbox.ui import attrs
|
||||
from netbox.ui.actions import CopyContent
|
||||
from utilities.data import resolve_attr_path
|
||||
from utilities.permissions import get_permission_for_model
|
||||
from utilities.querydict import dict_to_querydict
|
||||
from utilities.string import title
|
||||
from utilities.templatetags.plugins import _get_registered_content
|
||||
@@ -74,6 +75,15 @@ class Panel:
|
||||
'panel_class': self.__class__.__name__,
|
||||
}
|
||||
|
||||
def should_render(self, context):
|
||||
"""
|
||||
Determines whether the panel should render on the page. (Default: True)
|
||||
|
||||
Parameters:
|
||||
context (dict): The panel's prepared context (the return value of get_context())
|
||||
"""
|
||||
return True
|
||||
|
||||
def render(self, context):
|
||||
"""
|
||||
Render the panel as HTML.
|
||||
@@ -81,7 +91,10 @@ class Panel:
|
||||
Parameters:
|
||||
context (dict): The template context
|
||||
"""
|
||||
return render_to_string(self.template_name, self.get_context(context))
|
||||
ctx = self.get_context(context)
|
||||
if not self.should_render(ctx):
|
||||
return ''
|
||||
return render_to_string(self.template_name, ctx, request=ctx.get('request'))
|
||||
|
||||
|
||||
#
|
||||
@@ -314,6 +327,16 @@ class ObjectsTablePanel(Panel):
|
||||
'url_params': dict_to_querydict(url_params),
|
||||
}
|
||||
|
||||
def should_render(self, context):
|
||||
"""
|
||||
Hide the panel if the user does not have view permission for the panel's model.
|
||||
"""
|
||||
request = context.get('request')
|
||||
if request is None:
|
||||
return True
|
||||
|
||||
return request.user.has_perm(get_permission_for_model(self.model, 'view'))
|
||||
|
||||
|
||||
class TemplatePanel(Panel):
|
||||
"""
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Build local for local documentation
|
||||
@@ -31,29 +31,29 @@
|
||||
"gridstack": "12.4.2",
|
||||
"htmx.org": "2.0.8",
|
||||
"query-string": "9.3.1",
|
||||
"sass": "1.98.0",
|
||||
"sass": "1.99.0",
|
||||
"tom-select": "2.5.2",
|
||||
"typeface-inter": "3.18.1",
|
||||
"typeface-roboto-mono": "1.1.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^2.0.3",
|
||||
"@eslint/compat": "^2.0.5",
|
||||
"@eslint/eslintrc": "^3.3.5",
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@types/bootstrap": "5.2.10",
|
||||
"@types/cookie": "^1.0.0",
|
||||
"@types/node": "^24.10.1",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
||||
"@typescript-eslint/parser": "^8.57.0",
|
||||
"esbuild": "^0.27.4",
|
||||
"@typescript-eslint/eslint-plugin": "^8.58.2",
|
||||
"@typescript-eslint/parser": "^8.58.2",
|
||||
"esbuild": "^0.28.0",
|
||||
"esbuild-sass-plugin": "^3.7.0",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint": "^10.2.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-prettier": "^5.5.5",
|
||||
"globals": "^17.4.0",
|
||||
"prettier": "^3.8.1",
|
||||
"globals": "^17.5.0",
|
||||
"prettier": "^3.8.2",
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
@@ -24,135 +24,135 @@
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@esbuild/aix-ppc64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz#4c585002f7ad694d38fe0e8cbf5cfd939ccff327"
|
||||
integrity sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==
|
||||
"@esbuild/aix-ppc64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz#7a289c158e29cbf59ea0afc83cc80f06d1c89402"
|
||||
integrity sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==
|
||||
|
||||
"@esbuild/android-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz#7625d0952c3b402d3ede203a16c9f2b78f8a4827"
|
||||
integrity sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==
|
||||
"@esbuild/android-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz#b8828d9edfa3a92660644eb8de6e4f3c203d7b17"
|
||||
integrity sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==
|
||||
|
||||
"@esbuild/android-arm@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.4.tgz#9a0cf1d12997ec46dddfb32ce67e9bca842381ac"
|
||||
integrity sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==
|
||||
"@esbuild/android-arm@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.0.tgz#5ec1847605e05b5dbe5df90db9ff7e3e4c58dca7"
|
||||
integrity sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==
|
||||
|
||||
"@esbuild/android-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.4.tgz#06e1fdc6283fccd6bc6aadd6754afce6cf96f42e"
|
||||
integrity sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==
|
||||
"@esbuild/android-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.0.tgz#390642175b88ef82bad4cce03f8ab13fe9b1912e"
|
||||
integrity sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==
|
||||
|
||||
"@esbuild/darwin-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz#6c550ee6c0273bcb0fac244478ff727c26755d80"
|
||||
integrity sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==
|
||||
"@esbuild/darwin-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz#ae45325960d5950cd6951e4f97396f4e1ff7d8d3"
|
||||
integrity sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==
|
||||
|
||||
"@esbuild/darwin-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz#ed7a125e9f25ce0091b9aff783ee943f6ba6cb86"
|
||||
integrity sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==
|
||||
"@esbuild/darwin-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz#c079247d589b6b99449659d94f06951b84bff2e4"
|
||||
integrity sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz#597dc8e7161dba71db4c1656131c1f1e9d7660c6"
|
||||
integrity sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==
|
||||
"@esbuild/freebsd-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz#45c456215a486593c94900297202dc11c880a37a"
|
||||
integrity sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==
|
||||
|
||||
"@esbuild/freebsd-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz#ea171f9f4f00efaa8e9d3fe8baa1b75d757d1b36"
|
||||
integrity sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==
|
||||
"@esbuild/freebsd-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz#0399494c1c85e4388e9b7040bd60d48f2a5b0d2c"
|
||||
integrity sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==
|
||||
|
||||
"@esbuild/linux-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz#e52d57f202369386e6dbcb3370a17a0491ab1464"
|
||||
integrity sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==
|
||||
"@esbuild/linux-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz#d6d9f09ef0de54116bf459a4d53cac7e0952fe39"
|
||||
integrity sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==
|
||||
|
||||
"@esbuild/linux-arm@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz#5e0c0b634908adbce0a02cebeba8b3acac263fb6"
|
||||
integrity sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==
|
||||
"@esbuild/linux-arm@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz#7b42ffa84c288ae94fdc431c1b28a89e3c3b9278"
|
||||
integrity sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==
|
||||
|
||||
"@esbuild/linux-ia32@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz#5f90f01f131652473ec06b038a14c49683e14ec7"
|
||||
integrity sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==
|
||||
"@esbuild/linux-ia32@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz#deb15d112ed8dd605346b6b953d23a21ff81253f"
|
||||
integrity sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==
|
||||
|
||||
"@esbuild/linux-loong64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz#63bacffdb99574c9318f9afbd0dd4fff76a837e3"
|
||||
integrity sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==
|
||||
"@esbuild/linux-loong64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz#81fb89d07eecc79b157dea61033757726fce0ca4"
|
||||
integrity sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==
|
||||
|
||||
"@esbuild/linux-mips64el@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz#c4b6952eca6a8efff67fee3671a3536c8e67b7eb"
|
||||
integrity sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==
|
||||
"@esbuild/linux-mips64el@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz#d0e42691b3ff7af9fb2217b70fc01f343bdb62bb"
|
||||
integrity sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==
|
||||
|
||||
"@esbuild/linux-ppc64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz#6dea67d3d98c6986f1b7769e4f1848e5ae47ad58"
|
||||
integrity sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==
|
||||
"@esbuild/linux-ppc64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz#389f3e5e98f17d477c467cc87136e1a076eead87"
|
||||
integrity sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==
|
||||
|
||||
"@esbuild/linux-riscv64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz#9ad2b4c3c0502c6bada9c81997bb56c597853489"
|
||||
integrity sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==
|
||||
"@esbuild/linux-riscv64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz#763bd60d59b242be12da1e67d5729f3024c605fa"
|
||||
integrity sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==
|
||||
|
||||
"@esbuild/linux-s390x@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz#c43d3cfd073042ca6f5c52bb9bc313ed2066ce28"
|
||||
integrity sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==
|
||||
"@esbuild/linux-s390x@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz#aac6061634872e4677de693bce8030d73b1fd055"
|
||||
integrity sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==
|
||||
|
||||
"@esbuild/linux-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz#45fa173e0591ac74d80d3cf76704713e14e2a4a6"
|
||||
integrity sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==
|
||||
"@esbuild/linux-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz#4f2917747188fe77632bcec65b2d84b422419779"
|
||||
integrity sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==
|
||||
|
||||
"@esbuild/netbsd-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz#366b0ef40cdb986fc751cbdad16e8c25fe1ba879"
|
||||
integrity sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==
|
||||
"@esbuild/netbsd-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz#814df0ae57a0c386814491b8397eeba82094a947"
|
||||
integrity sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==
|
||||
|
||||
"@esbuild/netbsd-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz#e985d49a3668fd2044343071d52e1ae815112b3e"
|
||||
integrity sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==
|
||||
"@esbuild/netbsd-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz#e01bdf7e60fa1a08e46d46d960b0d9bb8ac210af"
|
||||
integrity sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz#6fb4ab7b73f7e5572ce5ec9cf91c13ff6dd44842"
|
||||
integrity sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==
|
||||
"@esbuild/openbsd-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz#4a15c36aacca68d2d5a4c90b710c06759f4c1ffa"
|
||||
integrity sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==
|
||||
|
||||
"@esbuild/openbsd-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz#641f052040a0d79843d68898f5791638a026d983"
|
||||
integrity sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==
|
||||
"@esbuild/openbsd-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz#475e6101498a8ecce3008d7c388111d7a27c17bd"
|
||||
integrity sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==
|
||||
|
||||
"@esbuild/openharmony-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz#fc1d33eac9d81ae0a433b3ed1dd6171a20d4e317"
|
||||
integrity sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==
|
||||
"@esbuild/openharmony-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz#cfdc3957f0b7a69f1bde129aad17fcc2f6fa033e"
|
||||
integrity sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==
|
||||
|
||||
"@esbuild/sunos-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz#af2cd5ca842d6d057121f66a192d4f797de28f53"
|
||||
integrity sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==
|
||||
"@esbuild/sunos-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz#a013c856fecacd1c3aec985c8afe1d1cb017497d"
|
||||
integrity sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==
|
||||
|
||||
"@esbuild/win32-arm64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz#78ec7e59bb06404583d4c9511e621db31c760de3"
|
||||
integrity sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==
|
||||
"@esbuild/win32-arm64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz#eae05e0f35271cad3898b43168d3e9a3bbaf47e5"
|
||||
integrity sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==
|
||||
|
||||
"@esbuild/win32-ia32@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz#0e616aa488b7ee5d2592ab070ff9ec06a9fddf11"
|
||||
integrity sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==
|
||||
"@esbuild/win32-ia32@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz#06161ebc5bf75c08d69feb3c6b22560515913998"
|
||||
integrity sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==
|
||||
|
||||
"@esbuild/win32-x64@0.27.4":
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz#1f7ba71a3d6155d44a6faa8dbe249c62ab3e408c"
|
||||
integrity sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==
|
||||
"@esbuild/win32-x64@0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz#04d90d5752b4ce65d2b6ac25eba08ff7624fe07c"
|
||||
integrity sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.8.0":
|
||||
version "4.9.0"
|
||||
@@ -168,63 +168,41 @@
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.12.2":
|
||||
"@eslint-community/regexpp@^4.12.2":
|
||||
version "4.12.2"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b"
|
||||
integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==
|
||||
|
||||
"@eslint/compat@^2.0.3":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/compat/-/compat-2.0.3.tgz#860bdd23d0df1c71a8d751f0aa1430e05bc056dd"
|
||||
integrity sha512-SjIJhGigp8hmd1YGIBwh7Ovri7Kisl42GYFjrOyHhtfYGGoLW6teYi/5p8W50KSsawUPpuLOSmsq1bD0NGQLBw==
|
||||
"@eslint/compat@^2.0.5":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/compat/-/compat-2.0.5.tgz#65421b3f6e5a864e0255ab31884fb26fdc4d0210"
|
||||
integrity sha512-IbHDbHJfkVNv6xjlET8AIVo/K1NQt7YT4Rp6ok/clyBGcpRx1l6gv0Rq3vBvYfPJIZt6ODf66Zq08FJNDpnzgg==
|
||||
dependencies:
|
||||
"@eslint/core" "^1.1.1"
|
||||
"@eslint/core" "^1.2.1"
|
||||
|
||||
"@eslint/config-array@^0.21.1":
|
||||
version "0.21.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713"
|
||||
integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==
|
||||
"@eslint/config-array@^0.23.4":
|
||||
version "0.23.5"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.23.5.tgz#56e86d243049195d8acc0c06a1b3dfdc3fa3de95"
|
||||
integrity sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==
|
||||
dependencies:
|
||||
"@eslint/object-schema" "^2.1.7"
|
||||
"@eslint/object-schema" "^3.0.5"
|
||||
debug "^4.3.1"
|
||||
minimatch "^3.1.2"
|
||||
minimatch "^10.2.4"
|
||||
|
||||
"@eslint/config-helpers@^0.4.2":
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda"
|
||||
integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==
|
||||
"@eslint/config-helpers@^0.5.4":
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.5.5.tgz#ae16134e4792ac5fbdc533548a24ac1ea9f7f3ae"
|
||||
integrity sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==
|
||||
dependencies:
|
||||
"@eslint/core" "^0.17.0"
|
||||
"@eslint/core" "^1.2.1"
|
||||
|
||||
"@eslint/core@^0.17.0":
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c"
|
||||
integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==
|
||||
"@eslint/core@^1.2.0", "@eslint/core@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/core/-/core-1.2.1.tgz#c1da7cd1b82fa8787f98b5629fb811848a1b63ce"
|
||||
integrity sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.15"
|
||||
|
||||
"@eslint/core@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/core/-/core-1.1.1.tgz#450f3d2be2d463ccd51119544092256b4e88df32"
|
||||
integrity sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.15"
|
||||
|
||||
"@eslint/eslintrc@^3.3.1":
|
||||
version "3.3.3"
|
||||
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz"
|
||||
integrity sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^10.0.1"
|
||||
globals "^14.0.0"
|
||||
ignore "^5.2.0"
|
||||
import-fresh "^3.2.1"
|
||||
js-yaml "^4.1.1"
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/eslintrc@^3.3.5":
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.5.tgz#c131793cfc1a7b96f24a83e0a8bbd4b881558c60"
|
||||
@@ -240,22 +218,22 @@
|
||||
minimatch "^3.1.5"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@9.39.2", "@eslint/js@^9.39.2":
|
||||
"@eslint/js@^9.39.2":
|
||||
version "9.39.2"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.2.tgz#2d4b8ec4c3ea13c1b3748e0c97ecd766bdd80599"
|
||||
integrity sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==
|
||||
|
||||
"@eslint/object-schema@^2.1.7":
|
||||
version "2.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad"
|
||||
integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==
|
||||
"@eslint/object-schema@^3.0.5":
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-3.0.5.tgz#88e9bf4d11d2b19c082e78ebe7ce88724a5eb091"
|
||||
integrity sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==
|
||||
|
||||
"@eslint/plugin-kit@^0.4.1":
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2"
|
||||
integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==
|
||||
"@eslint/plugin-kit@^0.7.0":
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz#c4125fd015eceeb09b793109fdbcd4dd0a02d346"
|
||||
integrity sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==
|
||||
dependencies:
|
||||
"@eslint/core" "^0.17.0"
|
||||
"@eslint/core" "^1.2.1"
|
||||
levn "^0.4.1"
|
||||
|
||||
"@floating-ui/core@^1.7.3":
|
||||
@@ -921,7 +899,12 @@
|
||||
dependencies:
|
||||
cookie "*"
|
||||
|
||||
"@types/estree@*", "@types/estree@^1.0.6":
|
||||
"@types/esrecurse@^4.3.1":
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/esrecurse/-/esrecurse-4.3.1.tgz#6f636af962fbe6191b830bd676ba5986926bccec"
|
||||
integrity sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==
|
||||
|
||||
"@types/estree@*", "@types/estree@^1.0.6", "@types/estree@^1.0.8":
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e"
|
||||
integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
|
||||
@@ -950,100 +933,100 @@
|
||||
dependencies:
|
||||
"@types/estree" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.0.tgz#6e4085604ab63f55b3dcc61ce2c16965b2c36374"
|
||||
integrity sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==
|
||||
"@typescript-eslint/eslint-plugin@^8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.58.2.tgz#a6882a6a328e1259cff259fdb03184245ef06191"
|
||||
integrity sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.12.2"
|
||||
"@typescript-eslint/scope-manager" "8.57.0"
|
||||
"@typescript-eslint/type-utils" "8.57.0"
|
||||
"@typescript-eslint/utils" "8.57.0"
|
||||
"@typescript-eslint/visitor-keys" "8.57.0"
|
||||
"@typescript-eslint/scope-manager" "8.58.2"
|
||||
"@typescript-eslint/type-utils" "8.58.2"
|
||||
"@typescript-eslint/utils" "8.58.2"
|
||||
"@typescript-eslint/visitor-keys" "8.58.2"
|
||||
ignore "^7.0.5"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^2.4.0"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/parser@^8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.57.0.tgz#444c57a943e8b04f255cda18a94c8e023b46b08c"
|
||||
integrity sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==
|
||||
"@typescript-eslint/parser@^8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.58.2.tgz#b267545e4bd515d896fe1f3a5b6f334fa6aa0026"
|
||||
integrity sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.57.0"
|
||||
"@typescript-eslint/types" "8.57.0"
|
||||
"@typescript-eslint/typescript-estree" "8.57.0"
|
||||
"@typescript-eslint/visitor-keys" "8.57.0"
|
||||
"@typescript-eslint/scope-manager" "8.58.2"
|
||||
"@typescript-eslint/types" "8.58.2"
|
||||
"@typescript-eslint/typescript-estree" "8.58.2"
|
||||
"@typescript-eslint/visitor-keys" "8.58.2"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/project-service@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.57.0.tgz#2014ed527bcd0eff8aecb7e44879ae3150604ab3"
|
||||
integrity sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==
|
||||
"@typescript-eslint/project-service@8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.58.2.tgz#8c980249100e21b87baba0ca10880fdf893e0a8e"
|
||||
integrity sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==
|
||||
dependencies:
|
||||
"@typescript-eslint/tsconfig-utils" "^8.57.0"
|
||||
"@typescript-eslint/types" "^8.57.0"
|
||||
"@typescript-eslint/tsconfig-utils" "^8.58.2"
|
||||
"@typescript-eslint/types" "^8.58.2"
|
||||
debug "^4.4.3"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz#7d2a2aeaaef2ae70891b21939fadb4cb0b19f840"
|
||||
integrity sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==
|
||||
"@typescript-eslint/scope-manager@8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.58.2.tgz#aa73784d78f117940e83f71705af07ba695cd60c"
|
||||
integrity sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.57.0"
|
||||
"@typescript-eslint/visitor-keys" "8.57.0"
|
||||
"@typescript-eslint/types" "8.58.2"
|
||||
"@typescript-eslint/visitor-keys" "8.58.2"
|
||||
|
||||
"@typescript-eslint/tsconfig-utils@8.57.0", "@typescript-eslint/tsconfig-utils@^8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz#cf2f2822af3887d25dd325b6bea6c3f60a83a0b4"
|
||||
integrity sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==
|
||||
"@typescript-eslint/tsconfig-utils@8.58.2", "@typescript-eslint/tsconfig-utils@^8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.2.tgz#fa13f96432c9348bf87f6f44826def585fad7bca"
|
||||
integrity sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==
|
||||
|
||||
"@typescript-eslint/type-utils@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.57.0.tgz#2877af4c2e8f0998b93a07dad1c34ce1bb669448"
|
||||
integrity sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==
|
||||
"@typescript-eslint/type-utils@8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.58.2.tgz#024eb1dd597f8a34cb22d8d9ab32da857bc9a817"
|
||||
integrity sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.57.0"
|
||||
"@typescript-eslint/typescript-estree" "8.57.0"
|
||||
"@typescript-eslint/utils" "8.57.0"
|
||||
"@typescript-eslint/types" "8.58.2"
|
||||
"@typescript-eslint/typescript-estree" "8.58.2"
|
||||
"@typescript-eslint/utils" "8.58.2"
|
||||
debug "^4.4.3"
|
||||
ts-api-utils "^2.4.0"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/types@8.57.0", "@typescript-eslint/types@^8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.57.0.tgz#4fa5385ffd1cd161fa5b9dce93e0493d491b8dc6"
|
||||
integrity sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==
|
||||
"@typescript-eslint/types@8.58.2", "@typescript-eslint/types@^8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.58.2.tgz#3ab8051de0f19a46ddefb0749d0f7d82974bd57c"
|
||||
integrity sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz#e0e4a89bfebb207de314826df876e2dabc7dea04"
|
||||
integrity sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==
|
||||
"@typescript-eslint/typescript-estree@8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.2.tgz#b1beb1f959385b341cc76f0aebbf028e23dfdb8b"
|
||||
integrity sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==
|
||||
dependencies:
|
||||
"@typescript-eslint/project-service" "8.57.0"
|
||||
"@typescript-eslint/tsconfig-utils" "8.57.0"
|
||||
"@typescript-eslint/types" "8.57.0"
|
||||
"@typescript-eslint/visitor-keys" "8.57.0"
|
||||
"@typescript-eslint/project-service" "8.58.2"
|
||||
"@typescript-eslint/tsconfig-utils" "8.58.2"
|
||||
"@typescript-eslint/types" "8.58.2"
|
||||
"@typescript-eslint/visitor-keys" "8.58.2"
|
||||
debug "^4.4.3"
|
||||
minimatch "^10.2.2"
|
||||
semver "^7.7.3"
|
||||
tinyglobby "^0.2.15"
|
||||
ts-api-utils "^2.4.0"
|
||||
ts-api-utils "^2.5.0"
|
||||
|
||||
"@typescript-eslint/utils@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.57.0.tgz#c7193385b44529b788210d20c94c11de79ad3498"
|
||||
integrity sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==
|
||||
"@typescript-eslint/utils@8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.58.2.tgz#27165554a02d1ff57d98262fa92060498dabc8b3"
|
||||
integrity sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.9.1"
|
||||
"@typescript-eslint/scope-manager" "8.57.0"
|
||||
"@typescript-eslint/types" "8.57.0"
|
||||
"@typescript-eslint/typescript-estree" "8.57.0"
|
||||
"@typescript-eslint/scope-manager" "8.58.2"
|
||||
"@typescript-eslint/types" "8.58.2"
|
||||
"@typescript-eslint/typescript-estree" "8.58.2"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz#23aea662279bb66209700854453807a119350f85"
|
||||
integrity sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==
|
||||
"@typescript-eslint/visitor-keys@8.58.2":
|
||||
version "8.58.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.2.tgz#9ed699eaa9b5720b6b6b6f9c16e6c7d4cd32b276"
|
||||
integrity sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.57.0"
|
||||
"@typescript-eslint/types" "8.58.2"
|
||||
eslint-visitor-keys "^5.0.0"
|
||||
|
||||
"@unrs/resolver-binding-android-arm-eabi@1.11.1":
|
||||
@@ -1153,15 +1136,10 @@ acorn@^8.15.0:
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz"
|
||||
integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==
|
||||
|
||||
ajv@^6.12.4:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
|
||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
acorn@^8.16.0:
|
||||
version "8.16.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a"
|
||||
integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==
|
||||
|
||||
ajv@^6.14.0:
|
||||
version "6.14.0"
|
||||
@@ -1173,13 +1151,6 @@ ajv@^6.14.0:
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
|
||||
@@ -1378,14 +1349,6 @@ callsites@^3.0.0:
|
||||
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
chalk@^4.0.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chokidar@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz"
|
||||
@@ -1425,18 +1388,6 @@ codemirror@^5.65.3:
|
||||
resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.65.20.tgz"
|
||||
integrity sha512-i5dLDDxwkFCbhjvL2pNjShsojoL3XHyDwsGv1jqETUoW+lzpBKKqNTUWgQwVAOa0tUm4BwekT455ujafi8payA==
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
|
||||
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||
@@ -1802,37 +1753,37 @@ esbuild-sass-plugin@^3.7.0:
|
||||
resolve "^1.22.11"
|
||||
sass "^1.97.3"
|
||||
|
||||
esbuild@^0.27.4:
|
||||
version "0.27.4"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.27.4.tgz#b9591dd7e0ab803a11c9c3b602850403bef22f00"
|
||||
integrity sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==
|
||||
esbuild@^0.28.0:
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.0.tgz#5dee347ffb3e3874212a35a69836b077b1ce6d96"
|
||||
integrity sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==
|
||||
optionalDependencies:
|
||||
"@esbuild/aix-ppc64" "0.27.4"
|
||||
"@esbuild/android-arm" "0.27.4"
|
||||
"@esbuild/android-arm64" "0.27.4"
|
||||
"@esbuild/android-x64" "0.27.4"
|
||||
"@esbuild/darwin-arm64" "0.27.4"
|
||||
"@esbuild/darwin-x64" "0.27.4"
|
||||
"@esbuild/freebsd-arm64" "0.27.4"
|
||||
"@esbuild/freebsd-x64" "0.27.4"
|
||||
"@esbuild/linux-arm" "0.27.4"
|
||||
"@esbuild/linux-arm64" "0.27.4"
|
||||
"@esbuild/linux-ia32" "0.27.4"
|
||||
"@esbuild/linux-loong64" "0.27.4"
|
||||
"@esbuild/linux-mips64el" "0.27.4"
|
||||
"@esbuild/linux-ppc64" "0.27.4"
|
||||
"@esbuild/linux-riscv64" "0.27.4"
|
||||
"@esbuild/linux-s390x" "0.27.4"
|
||||
"@esbuild/linux-x64" "0.27.4"
|
||||
"@esbuild/netbsd-arm64" "0.27.4"
|
||||
"@esbuild/netbsd-x64" "0.27.4"
|
||||
"@esbuild/openbsd-arm64" "0.27.4"
|
||||
"@esbuild/openbsd-x64" "0.27.4"
|
||||
"@esbuild/openharmony-arm64" "0.27.4"
|
||||
"@esbuild/sunos-x64" "0.27.4"
|
||||
"@esbuild/win32-arm64" "0.27.4"
|
||||
"@esbuild/win32-ia32" "0.27.4"
|
||||
"@esbuild/win32-x64" "0.27.4"
|
||||
"@esbuild/aix-ppc64" "0.28.0"
|
||||
"@esbuild/android-arm" "0.28.0"
|
||||
"@esbuild/android-arm64" "0.28.0"
|
||||
"@esbuild/android-x64" "0.28.0"
|
||||
"@esbuild/darwin-arm64" "0.28.0"
|
||||
"@esbuild/darwin-x64" "0.28.0"
|
||||
"@esbuild/freebsd-arm64" "0.28.0"
|
||||
"@esbuild/freebsd-x64" "0.28.0"
|
||||
"@esbuild/linux-arm" "0.28.0"
|
||||
"@esbuild/linux-arm64" "0.28.0"
|
||||
"@esbuild/linux-ia32" "0.28.0"
|
||||
"@esbuild/linux-loong64" "0.28.0"
|
||||
"@esbuild/linux-mips64el" "0.28.0"
|
||||
"@esbuild/linux-ppc64" "0.28.0"
|
||||
"@esbuild/linux-riscv64" "0.28.0"
|
||||
"@esbuild/linux-s390x" "0.28.0"
|
||||
"@esbuild/linux-x64" "0.28.0"
|
||||
"@esbuild/netbsd-arm64" "0.28.0"
|
||||
"@esbuild/netbsd-x64" "0.28.0"
|
||||
"@esbuild/openbsd-arm64" "0.28.0"
|
||||
"@esbuild/openbsd-x64" "0.28.0"
|
||||
"@esbuild/openharmony-arm64" "0.28.0"
|
||||
"@esbuild/sunos-x64" "0.28.0"
|
||||
"@esbuild/win32-arm64" "0.28.0"
|
||||
"@esbuild/win32-ia32" "0.28.0"
|
||||
"@esbuild/win32-x64" "0.28.0"
|
||||
|
||||
escape-string-regexp@^4.0.0:
|
||||
version "4.0.0"
|
||||
@@ -1914,11 +1865,13 @@ eslint-plugin-prettier@^5.5.5:
|
||||
prettier-linter-helpers "^1.0.1"
|
||||
synckit "^0.11.12"
|
||||
|
||||
eslint-scope@^8.4.0:
|
||||
version "8.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82"
|
||||
integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==
|
||||
eslint-scope@^9.1.2:
|
||||
version "9.1.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-9.1.2.tgz#b9de6ace2fab1cff24d2e58d85b74c8fcea39802"
|
||||
integrity sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==
|
||||
dependencies:
|
||||
"@types/esrecurse" "^4.3.1"
|
||||
"@types/estree" "^1.0.8"
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
@@ -1937,32 +1890,34 @@ eslint-visitor-keys@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.0.tgz#b9aa1a74aa48c44b3ae46c1597ce7171246a94a9"
|
||||
integrity sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q==
|
||||
|
||||
eslint@^9.39.2:
|
||||
version "9.39.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.2.tgz#cb60e6d16ab234c0f8369a3fe7cc87967faf4b6c"
|
||||
integrity sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==
|
||||
eslint-visitor-keys@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be"
|
||||
integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==
|
||||
|
||||
eslint@^10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-10.2.0.tgz#711c80d32fc3fdd3a575bb93977df43887c3ec8e"
|
||||
integrity sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.8.0"
|
||||
"@eslint-community/regexpp" "^4.12.1"
|
||||
"@eslint/config-array" "^0.21.1"
|
||||
"@eslint/config-helpers" "^0.4.2"
|
||||
"@eslint/core" "^0.17.0"
|
||||
"@eslint/eslintrc" "^3.3.1"
|
||||
"@eslint/js" "9.39.2"
|
||||
"@eslint/plugin-kit" "^0.4.1"
|
||||
"@eslint-community/regexpp" "^4.12.2"
|
||||
"@eslint/config-array" "^0.23.4"
|
||||
"@eslint/config-helpers" "^0.5.4"
|
||||
"@eslint/core" "^1.2.0"
|
||||
"@eslint/plugin-kit" "^0.7.0"
|
||||
"@humanfs/node" "^0.16.6"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@humanwhocodes/retry" "^0.4.2"
|
||||
"@types/estree" "^1.0.6"
|
||||
ajv "^6.12.4"
|
||||
chalk "^4.0.0"
|
||||
ajv "^6.14.0"
|
||||
cross-spawn "^7.0.6"
|
||||
debug "^4.3.2"
|
||||
escape-string-regexp "^4.0.0"
|
||||
eslint-scope "^8.4.0"
|
||||
eslint-visitor-keys "^4.2.1"
|
||||
espree "^10.4.0"
|
||||
esquery "^1.5.0"
|
||||
eslint-scope "^9.1.2"
|
||||
eslint-visitor-keys "^5.0.1"
|
||||
espree "^11.2.0"
|
||||
esquery "^1.7.0"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
file-entry-cache "^8.0.0"
|
||||
@@ -1972,12 +1927,11 @@ eslint@^9.39.2:
|
||||
imurmurhash "^0.1.4"
|
||||
is-glob "^4.0.0"
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
lodash.merge "^4.6.2"
|
||||
minimatch "^3.1.2"
|
||||
minimatch "^10.2.4"
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.3"
|
||||
|
||||
espree@^10.0.1, espree@^10.4.0:
|
||||
espree@^10.0.1:
|
||||
version "10.4.0"
|
||||
resolved "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz"
|
||||
integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==
|
||||
@@ -1986,10 +1940,19 @@ espree@^10.0.1, espree@^10.4.0:
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^4.2.1"
|
||||
|
||||
esquery@^1.5.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
|
||||
integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
|
||||
espree@^11.2.0:
|
||||
version "11.2.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-11.2.0.tgz#01d5e47dc332aaba3059008362454a8cc34ccaa5"
|
||||
integrity sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==
|
||||
dependencies:
|
||||
acorn "^8.16.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^5.0.1"
|
||||
|
||||
esquery@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d"
|
||||
integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==
|
||||
dependencies:
|
||||
estraverse "^5.1.0"
|
||||
|
||||
@@ -2219,10 +2182,10 @@ globals@^14.0.0:
|
||||
resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz"
|
||||
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
|
||||
|
||||
globals@^17.4.0:
|
||||
version "17.4.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-17.4.0.tgz#33d7d297ed1536b388a0e2f4bcd0ff19c8ff91b5"
|
||||
integrity sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==
|
||||
globals@^17.5.0:
|
||||
version "17.5.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-17.5.0.tgz#a82c641d898f8dfbe0e81f66fdff7d0de43f88c6"
|
||||
integrity sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==
|
||||
|
||||
globalthis@^1.0.3, globalthis@^1.0.4:
|
||||
version "1.0.4"
|
||||
@@ -2290,11 +2253,6 @@ has-bigints@^1.0.1, has-bigints@^1.0.2:
|
||||
resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz"
|
||||
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
|
||||
|
||||
has-flag@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz"
|
||||
@@ -2767,11 +2725,6 @@ locate-path@^6.0.0:
|
||||
dependencies:
|
||||
p-locate "^5.0.0"
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
||||
@@ -2821,7 +2774,7 @@ minimatch@^10.2.2:
|
||||
dependencies:
|
||||
brace-expansion "^5.0.2"
|
||||
|
||||
minimatch@^3.1.2, minimatch@^3.1.3, minimatch@^3.1.5:
|
||||
minimatch@^10.2.4, minimatch@^3.1.2, minimatch@^3.1.3, minimatch@^3.1.5:
|
||||
version "3.1.5"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e"
|
||||
integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==
|
||||
@@ -2993,22 +2946,12 @@ path-parse@^1.0.7:
|
||||
resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
picomatch@2.3.2:
|
||||
picomatch@2.3.2, picomatch@^2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601"
|
||||
integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==
|
||||
|
||||
picomatch@4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589"
|
||||
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==
|
||||
|
||||
picomatch@^2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601"
|
||||
integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==
|
||||
|
||||
picomatch@^4.0.3:
|
||||
picomatch@4.0.4, picomatch@^4.0.3:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589"
|
||||
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==
|
||||
@@ -3030,10 +2973,10 @@ prettier-linter-helpers@^1.0.1:
|
||||
dependencies:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@^3.8.1:
|
||||
version "3.8.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.1.tgz#edf48977cf991558f4fcbd8a3ba6015ba2a3a173"
|
||||
integrity sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==
|
||||
prettier@^3.8.2:
|
||||
version "3.8.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.2.tgz#4f52e502193c9aa5b384c3d00852003e551bbd9f"
|
||||
integrity sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==
|
||||
|
||||
punycode.js@^2.3.1:
|
||||
version "2.3.1"
|
||||
@@ -3217,7 +3160,18 @@ safe-regex-test@^1.1.0:
|
||||
es-errors "^1.3.0"
|
||||
is-regex "^1.2.1"
|
||||
|
||||
sass@1.98.0, sass@^1.97.3:
|
||||
sass@1.99.0:
|
||||
version "1.99.0"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.99.0.tgz#ff9d1594da4886249dfaafabbeea2dea2dc74b26"
|
||||
integrity sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==
|
||||
dependencies:
|
||||
chokidar "^4.0.0"
|
||||
immutable "^5.1.5"
|
||||
source-map-js ">=0.6.2 <2.0.0"
|
||||
optionalDependencies:
|
||||
"@parcel/watcher" "^2.4.1"
|
||||
|
||||
sass@^1.97.3:
|
||||
version "1.98.0"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.98.0.tgz#924ce85a3745ccaccd976262fdc1bc0c13aa8e57"
|
||||
integrity sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==
|
||||
@@ -3435,13 +3389,6 @@ strip-json-comments@^3.1.1:
|
||||
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
supports-preserve-symlinks-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
|
||||
@@ -3492,10 +3439,10 @@ tom-select@2.5.2:
|
||||
"@orchidjs/sifter" "^1.1.0"
|
||||
"@orchidjs/unicode-variants" "^1.1.2"
|
||||
|
||||
ts-api-utils@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.4.0.tgz#2690579f96d2790253bdcf1ca35d569ad78f9ad8"
|
||||
integrity sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==
|
||||
ts-api-utils@^2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.5.0.tgz#4acd4a155e22734990a5ed1fe9e97f113bcb37c1"
|
||||
integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==
|
||||
|
||||
tsconfig-paths@^3.15.0:
|
||||
version "3.15.0"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version: "4.5.7"
|
||||
version: "4.5.8"
|
||||
edition: "Community"
|
||||
published: "2026-04-03"
|
||||
published: "2026-04-14"
|
||||
|
||||
@@ -42,13 +42,7 @@ class TenantViewSet(NetBoxModelViewSet):
|
||||
#
|
||||
|
||||
class ContactGroupViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
||||
queryset = ContactGroup.objects.add_related_count(
|
||||
ContactGroup.objects.all(),
|
||||
Contact,
|
||||
'groups',
|
||||
'contact_count',
|
||||
cumulative=True
|
||||
)
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
serializer_class = serializers.ContactGroupSerializer
|
||||
filterset_class = filtersets.ContactGroupFilterSet
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.db.models.expressions import RawSQL
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from netbox.models import ChangeLoggedModel, NestedGroupModel, OrganizationalModel, PrimaryModel
|
||||
from netbox.models.features import CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, has_feature
|
||||
from tenancy.choices import *
|
||||
from utilities.mptt import TreeManager
|
||||
|
||||
__all__ = (
|
||||
'Contact',
|
||||
@@ -16,10 +18,34 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class ContactGroupManager(TreeManager):
|
||||
|
||||
def annotate_contacts(self):
|
||||
"""
|
||||
Annotate the total number of Contacts belonging to each ContactGroup.
|
||||
|
||||
This returns both direct children and children of child groups. Raw SQL is used here to avoid double-counting
|
||||
contacts which are assigned to multiple child groups of the parent.
|
||||
"""
|
||||
return self.annotate(
|
||||
contact_count=RawSQL(
|
||||
"SELECT COUNT(DISTINCT m2m.contact_id)"
|
||||
" FROM tenancy_contact_groups m2m"
|
||||
" INNER JOIN tenancy_contactgroup cg ON m2m.contactgroup_id = cg.id"
|
||||
" WHERE cg.tree_id = tenancy_contactgroup.tree_id"
|
||||
" AND cg.lft >= tenancy_contactgroup.lft"
|
||||
" AND cg.lft <= tenancy_contactgroup.rght",
|
||||
()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class ContactGroup(NestedGroupModel):
|
||||
"""
|
||||
An arbitrary collection of Contacts.
|
||||
"""
|
||||
objects = ContactGroupManager()
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
# Empty tuple triggers Django migration detection for MPTT indexes
|
||||
|
||||
72
netbox/tenancy/tests/test_models.py
Normal file
72
netbox/tenancy/tests/test_models.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from tenancy.models import Contact, ContactGroup
|
||||
|
||||
|
||||
class ContactGroupTestCase(TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
# Create a tree of contact groups:
|
||||
# - Group A
|
||||
# - Group A1
|
||||
# - Group A2
|
||||
# - Group B
|
||||
cls.group_a = ContactGroup.objects.create(name='Group A', slug='group-a')
|
||||
cls.group_a1 = ContactGroup.objects.create(name='Group A1', slug='group-a1', parent=cls.group_a)
|
||||
cls.group_a2 = ContactGroup.objects.create(name='Group A2', slug='group-a2', parent=cls.group_a)
|
||||
cls.group_b = ContactGroup.objects.create(name='Group B', slug='group-b')
|
||||
|
||||
# Create contacts
|
||||
cls.contact1 = Contact.objects.create(name='Contact 1')
|
||||
cls.contact2 = Contact.objects.create(name='Contact 2')
|
||||
cls.contact3 = Contact.objects.create(name='Contact 3')
|
||||
cls.contact4 = Contact.objects.create(name='Contact 4')
|
||||
|
||||
def test_annotate_contacts_direct(self):
|
||||
"""Contacts assigned directly to a group should be counted."""
|
||||
self.contact1.groups.set([self.group_a])
|
||||
self.contact2.groups.set([self.group_a])
|
||||
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
self.assertEqual(queryset.get(pk=self.group_a.pk).contact_count, 2)
|
||||
|
||||
def test_annotate_contacts_cumulative(self):
|
||||
"""Contacts assigned to child groups should be included in the parent's count."""
|
||||
self.contact1.groups.set([self.group_a1])
|
||||
self.contact2.groups.set([self.group_a2])
|
||||
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
self.assertEqual(queryset.get(pk=self.group_a.pk).contact_count, 2)
|
||||
self.assertEqual(queryset.get(pk=self.group_a1.pk).contact_count, 1)
|
||||
self.assertEqual(queryset.get(pk=self.group_a2.pk).contact_count, 1)
|
||||
|
||||
def test_annotate_contacts_no_double_counting(self):
|
||||
"""A contact assigned to multiple child groups must be counted only once for the parent."""
|
||||
self.contact1.groups.set([self.group_a1, self.group_a2])
|
||||
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
self.assertEqual(queryset.get(pk=self.group_a.pk).contact_count, 1)
|
||||
|
||||
def test_annotate_contacts_mixed(self):
|
||||
"""Test a mix of direct and inherited contacts with overlap."""
|
||||
self.contact1.groups.set([self.group_a])
|
||||
self.contact2.groups.set([self.group_a1])
|
||||
self.contact3.groups.set([self.group_a1, self.group_a2])
|
||||
self.contact4.groups.set([self.group_b])
|
||||
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
# Group A: contact1 (direct) + contact2 (via A1) + contact3 (via A1 & A2) = 3
|
||||
self.assertEqual(queryset.get(pk=self.group_a.pk).contact_count, 3)
|
||||
# Group A1: contact2 + contact3 = 2
|
||||
self.assertEqual(queryset.get(pk=self.group_a1.pk).contact_count, 2)
|
||||
# Group A2: contact3 = 1
|
||||
self.assertEqual(queryset.get(pk=self.group_a2.pk).contact_count, 1)
|
||||
# Group B: contact4 = 1
|
||||
self.assertEqual(queryset.get(pk=self.group_b.pk).contact_count, 1)
|
||||
|
||||
def test_annotate_contacts_empty(self):
|
||||
"""Groups with no contacts should return a count of zero."""
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
self.assertEqual(queryset.get(pk=self.group_a.pk).contact_count, 0)
|
||||
self.assertEqual(queryset.get(pk=self.group_b.pk).contact_count, 0)
|
||||
@@ -205,13 +205,7 @@ class TenantBulkDeleteView(generic.BulkDeleteView):
|
||||
|
||||
@register_model_view(ContactGroup, 'list', path='', detail=False)
|
||||
class ContactGroupListView(generic.ObjectListView):
|
||||
queryset = ContactGroup.objects.add_related_count(
|
||||
ContactGroup.objects.all(),
|
||||
Contact,
|
||||
'groups',
|
||||
'contact_count',
|
||||
cumulative=True
|
||||
)
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
filterset = filtersets.ContactGroupFilterSet
|
||||
filterset_form = forms.ContactGroupFilterForm
|
||||
table = tables.ContactGroupTable
|
||||
@@ -254,7 +248,7 @@ class ContactGroupView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
request,
|
||||
groups,
|
||||
extra=(
|
||||
(Contact.objects.restrict(request.user, 'view').filter(groups__in=groups), 'group_id'),
|
||||
(Contact.objects.restrict(request.user, 'view').filter(groups__in=groups).distinct(), 'group_id'),
|
||||
),
|
||||
),
|
||||
}
|
||||
@@ -280,13 +274,7 @@ class ContactGroupBulkImportView(generic.BulkImportView):
|
||||
|
||||
@register_model_view(ContactGroup, 'bulk_edit', path='edit', detail=False)
|
||||
class ContactGroupBulkEditView(generic.BulkEditView):
|
||||
queryset = ContactGroup.objects.add_related_count(
|
||||
ContactGroup.objects.all(),
|
||||
Contact,
|
||||
'groups',
|
||||
'contact_count',
|
||||
cumulative=True
|
||||
)
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
filterset = filtersets.ContactGroupFilterSet
|
||||
table = tables.ContactGroupTable
|
||||
form = forms.ContactGroupBulkEditForm
|
||||
@@ -300,13 +288,7 @@ class ContactGroupBulkRenameView(generic.BulkRenameView):
|
||||
|
||||
@register_model_view(ContactGroup, 'bulk_delete', path='delete', detail=False)
|
||||
class ContactGroupBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = ContactGroup.objects.add_related_count(
|
||||
ContactGroup.objects.all(),
|
||||
Contact,
|
||||
'groups',
|
||||
'contact_count',
|
||||
cumulative=True
|
||||
)
|
||||
queryset = ContactGroup.objects.annotate_contacts()
|
||||
filterset = filtersets.ContactGroupFilterSet
|
||||
table = tables.ContactGroupTable
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-10 05:39+0000\n"
|
||||
"POT-Creation-Date: 2026-04-14 05:39+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -173,8 +173,8 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_edit.py:329 netbox/dcim/forms/bulk_edit.py:679
|
||||
#: netbox/dcim/forms/bulk_edit.py:866 netbox/dcim/forms/bulk_import.py:146
|
||||
#: netbox/dcim/forms/bulk_import.py:247 netbox/dcim/forms/bulk_import.py:349
|
||||
#: netbox/dcim/forms/bulk_import.py:640 netbox/dcim/forms/bulk_import.py:1612
|
||||
#: netbox/dcim/forms/bulk_import.py:1640 netbox/dcim/forms/filtersets.py:106
|
||||
#: netbox/dcim/forms/bulk_import.py:640 netbox/dcim/forms/bulk_import.py:1659
|
||||
#: netbox/dcim/forms/bulk_import.py:1687 netbox/dcim/forms/filtersets.py:106
|
||||
#: netbox/dcim/forms/filtersets.py:256 netbox/dcim/forms/filtersets.py:379
|
||||
#: netbox/dcim/forms/filtersets.py:483 netbox/dcim/forms/filtersets.py:855
|
||||
#: netbox/dcim/forms/filtersets.py:1073 netbox/dcim/forms/filtersets.py:1147
|
||||
@@ -450,7 +450,7 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_edit.py:611 netbox/dcim/forms/bulk_edit.py:809
|
||||
#: netbox/dcim/forms/bulk_edit.py:1063 netbox/dcim/forms/bulk_edit.py:1162
|
||||
#: netbox/dcim/forms/bulk_edit.py:1189 netbox/dcim/forms/bulk_edit.py:1723
|
||||
#: netbox/dcim/forms/bulk_import.py:1484 netbox/dcim/forms/filtersets.py:1220
|
||||
#: netbox/dcim/forms/bulk_import.py:1500 netbox/dcim/forms/filtersets.py:1220
|
||||
#: netbox/dcim/forms/filtersets.py:1545 netbox/dcim/forms/filtersets.py:1761
|
||||
#: netbox/dcim/forms/filtersets.py:1780 netbox/dcim/forms/filtersets.py:1804
|
||||
#: netbox/dcim/forms/filtersets.py:1823 netbox/dcim/tables/devices.py:806
|
||||
@@ -481,8 +481,8 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_import.py:813 netbox/dcim/forms/bulk_import.py:839
|
||||
#: netbox/dcim/forms/bulk_import.py:865 netbox/dcim/forms/bulk_import.py:886
|
||||
#: netbox/dcim/forms/bulk_import.py:972 netbox/dcim/forms/bulk_import.py:1101
|
||||
#: netbox/dcim/forms/bulk_import.py:1120 netbox/dcim/forms/bulk_import.py:1465
|
||||
#: netbox/dcim/forms/bulk_import.py:1677 netbox/dcim/forms/filtersets.py:1104
|
||||
#: netbox/dcim/forms/bulk_import.py:1120 netbox/dcim/forms/bulk_import.py:1481
|
||||
#: netbox/dcim/forms/bulk_import.py:1724 netbox/dcim/forms/filtersets.py:1104
|
||||
#: netbox/dcim/forms/filtersets.py:1205 netbox/dcim/forms/filtersets.py:1333
|
||||
#: netbox/dcim/forms/filtersets.py:1424 netbox/dcim/forms/filtersets.py:1444
|
||||
#: netbox/dcim/forms/filtersets.py:1464 netbox/dcim/forms/filtersets.py:1484
|
||||
@@ -539,8 +539,8 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_import.py:103 netbox/dcim/forms/bulk_import.py:162
|
||||
#: netbox/dcim/forms/bulk_import.py:265 netbox/dcim/forms/bulk_import.py:374
|
||||
#: netbox/dcim/forms/bulk_import.py:605 netbox/dcim/forms/bulk_import.py:765
|
||||
#: netbox/dcim/forms/bulk_import.py:1230 netbox/dcim/forms/bulk_import.py:1453
|
||||
#: netbox/dcim/forms/bulk_import.py:1672 netbox/dcim/forms/bulk_import.py:1735
|
||||
#: netbox/dcim/forms/bulk_import.py:1230 netbox/dcim/forms/bulk_import.py:1469
|
||||
#: netbox/dcim/forms/bulk_import.py:1719 netbox/dcim/forms/bulk_import.py:1782
|
||||
#: netbox/dcim/forms/filtersets.py:208 netbox/dcim/forms/filtersets.py:268
|
||||
#: netbox/dcim/forms/filtersets.py:396 netbox/dcim/forms/filtersets.py:504
|
||||
#: netbox/dcim/forms/filtersets.py:901 netbox/dcim/forms/filtersets.py:1024
|
||||
@@ -601,8 +601,8 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_edit.py:799 netbox/dcim/forms/bulk_edit.py:1746
|
||||
#: netbox/dcim/forms/bulk_import.py:122 netbox/dcim/forms/bulk_import.py:167
|
||||
#: netbox/dcim/forms/bulk_import.py:258 netbox/dcim/forms/bulk_import.py:379
|
||||
#: netbox/dcim/forms/bulk_import.py:579 netbox/dcim/forms/bulk_import.py:1471
|
||||
#: netbox/dcim/forms/bulk_import.py:1728 netbox/dcim/forms/filtersets.py:143
|
||||
#: netbox/dcim/forms/bulk_import.py:579 netbox/dcim/forms/bulk_import.py:1487
|
||||
#: netbox/dcim/forms/bulk_import.py:1775 netbox/dcim/forms/filtersets.py:143
|
||||
#: netbox/dcim/forms/filtersets.py:202 netbox/dcim/forms/filtersets.py:235
|
||||
#: netbox/dcim/forms/filtersets.py:363 netbox/dcim/forms/filtersets.py:442
|
||||
#: netbox/dcim/forms/filtersets.py:463 netbox/dcim/forms/filtersets.py:823
|
||||
@@ -788,7 +788,7 @@ msgstr ""
|
||||
|
||||
#: netbox/circuits/forms/bulk_edit.py:192
|
||||
#: netbox/circuits/forms/model_forms.py:199
|
||||
#: netbox/dcim/forms/bulk_import.py:1419 netbox/dcim/forms/bulk_import.py:1444
|
||||
#: netbox/dcim/forms/bulk_import.py:1427 netbox/dcim/forms/bulk_import.py:1460
|
||||
msgid "Termination type"
|
||||
msgstr ""
|
||||
|
||||
@@ -915,7 +915,7 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_import.py:105 netbox/dcim/forms/bulk_import.py:164
|
||||
#: netbox/dcim/forms/bulk_import.py:267 netbox/dcim/forms/bulk_import.py:376
|
||||
#: netbox/dcim/forms/bulk_import.py:607 netbox/dcim/forms/bulk_import.py:767
|
||||
#: netbox/dcim/forms/bulk_import.py:1232 netbox/dcim/forms/bulk_import.py:1674
|
||||
#: netbox/dcim/forms/bulk_import.py:1232 netbox/dcim/forms/bulk_import.py:1721
|
||||
#: netbox/ipam/forms/bulk_import.py:200 netbox/ipam/forms/bulk_import.py:264
|
||||
#: netbox/ipam/forms/bulk_import.py:300 netbox/ipam/forms/bulk_import.py:531
|
||||
#: netbox/ipam/forms/bulk_import.py:544
|
||||
@@ -931,8 +931,8 @@ msgstr ""
|
||||
#: netbox/circuits/forms/bulk_import.py:235
|
||||
#: netbox/dcim/forms/bulk_import.py:126 netbox/dcim/forms/bulk_import.py:171
|
||||
#: netbox/dcim/forms/bulk_import.py:383 netbox/dcim/forms/bulk_import.py:583
|
||||
#: netbox/dcim/forms/bulk_import.py:1475 netbox/dcim/forms/bulk_import.py:1669
|
||||
#: netbox/dcim/forms/bulk_import.py:1732 netbox/ipam/forms/bulk_import.py:49
|
||||
#: netbox/dcim/forms/bulk_import.py:1491 netbox/dcim/forms/bulk_import.py:1716
|
||||
#: netbox/dcim/forms/bulk_import.py:1779 netbox/ipam/forms/bulk_import.py:49
|
||||
#: netbox/ipam/forms/bulk_import.py:78 netbox/ipam/forms/bulk_import.py:106
|
||||
#: netbox/ipam/forms/bulk_import.py:126 netbox/ipam/forms/bulk_import.py:146
|
||||
#: netbox/ipam/forms/bulk_import.py:174 netbox/ipam/forms/bulk_import.py:259
|
||||
@@ -1005,8 +1005,8 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_edit.py:445 netbox/dcim/forms/bulk_edit.py:684
|
||||
#: netbox/dcim/forms/bulk_edit.py:733 netbox/dcim/forms/bulk_edit.py:875
|
||||
#: netbox/dcim/forms/bulk_import.py:252 netbox/dcim/forms/bulk_import.py:355
|
||||
#: netbox/dcim/forms/bulk_import.py:646 netbox/dcim/forms/bulk_import.py:1618
|
||||
#: netbox/dcim/forms/bulk_import.py:1652 netbox/dcim/forms/filtersets.py:114
|
||||
#: netbox/dcim/forms/bulk_import.py:646 netbox/dcim/forms/bulk_import.py:1665
|
||||
#: netbox/dcim/forms/bulk_import.py:1699 netbox/dcim/forms/filtersets.py:114
|
||||
#: netbox/dcim/forms/filtersets.py:358 netbox/dcim/forms/filtersets.py:393
|
||||
#: netbox/dcim/forms/filtersets.py:438 netbox/dcim/forms/filtersets.py:491
|
||||
#: netbox/dcim/forms/filtersets.py:820 netbox/dcim/forms/filtersets.py:864
|
||||
@@ -1424,7 +1424,7 @@ msgstr ""
|
||||
#: netbox/extras/models/models.py:172 netbox/extras/models/models.py:314
|
||||
#: netbox/extras/models/models.py:417 netbox/extras/models/models.py:482
|
||||
#: netbox/extras/models/models.py:567 netbox/extras/models/models.py:692
|
||||
#: netbox/extras/models/notifications.py:126 netbox/extras/models/scripts.py:31
|
||||
#: netbox/extras/models/notifications.py:126 netbox/extras/models/scripts.py:29
|
||||
#: netbox/ipam/models/asns.py:18 netbox/ipam/models/fhrp.py:24
|
||||
#: netbox/ipam/models/services.py:51 netbox/ipam/models/services.py:80
|
||||
#: netbox/ipam/models/vlans.py:38 netbox/ipam/models/vlans.py:217
|
||||
@@ -1667,7 +1667,7 @@ msgstr ""
|
||||
#: netbox/dcim/forms/bulk_import.py:1096 netbox/dcim/forms/bulk_import.py:1115
|
||||
#: netbox/dcim/forms/bulk_import.py:1134 netbox/dcim/forms/bulk_import.py:1146
|
||||
#: netbox/dcim/forms/bulk_import.py:1194 netbox/dcim/forms/bulk_import.py:1316
|
||||
#: netbox/dcim/forms/bulk_import.py:1722 netbox/dcim/forms/connections.py:34
|
||||
#: netbox/dcim/forms/bulk_import.py:1769 netbox/dcim/forms/connections.py:34
|
||||
#: netbox/dcim/forms/filtersets.py:156 netbox/dcim/forms/filtersets.py:1021
|
||||
#: netbox/dcim/forms/filtersets.py:1054 netbox/dcim/forms/filtersets.py:1202
|
||||
#: netbox/dcim/forms/filtersets.py:1418 netbox/dcim/forms/filtersets.py:1441
|
||||
@@ -4255,8 +4255,8 @@ msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:444 netbox/dcim/forms/bulk_edit.py:897
|
||||
#: netbox/dcim/forms/bulk_import.py:362 netbox/dcim/forms/bulk_import.py:365
|
||||
#: netbox/dcim/forms/bulk_import.py:653 netbox/dcim/forms/bulk_import.py:1659
|
||||
#: netbox/dcim/forms/bulk_import.py:1663 netbox/dcim/forms/filtersets.py:123
|
||||
#: netbox/dcim/forms/bulk_import.py:653 netbox/dcim/forms/bulk_import.py:1706
|
||||
#: netbox/dcim/forms/bulk_import.py:1710 netbox/dcim/forms/filtersets.py:123
|
||||
#: netbox/dcim/forms/filtersets.py:359 netbox/dcim/forms/filtersets.py:448
|
||||
#: netbox/dcim/forms/filtersets.py:462 netbox/dcim/forms/filtersets.py:501
|
||||
#: netbox/dcim/forms/filtersets.py:874 netbox/dcim/forms/filtersets.py:1086
|
||||
@@ -4316,7 +4316,7 @@ msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:555 netbox/dcim/forms/bulk_edit.py:562
|
||||
#: netbox/dcim/forms/bulk_edit.py:793 netbox/dcim/forms/bulk_import.py:460
|
||||
#: netbox/dcim/forms/bulk_import.py:1459 netbox/dcim/forms/filtersets.py:690
|
||||
#: netbox/dcim/forms/bulk_import.py:1475 netbox/dcim/forms/filtersets.py:690
|
||||
#: netbox/dcim/forms/filtersets.py:1215 netbox/dcim/forms/model_forms.py:444
|
||||
#: netbox/dcim/forms/model_forms.py:457 netbox/dcim/tables/modules.py:43
|
||||
#: netbox/extras/forms/filtersets.py:413 netbox/extras/forms/model_forms.py:626
|
||||
@@ -4440,8 +4440,8 @@ msgstr ""
|
||||
msgid "Length"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:818 netbox/dcim/forms/bulk_import.py:1478
|
||||
#: netbox/dcim/forms/bulk_import.py:1481 netbox/dcim/forms/filtersets.py:1228
|
||||
#: netbox/dcim/forms/bulk_edit.py:818 netbox/dcim/forms/bulk_import.py:1494
|
||||
#: netbox/dcim/forms/bulk_import.py:1497 netbox/dcim/forms/filtersets.py:1228
|
||||
msgid "Length unit"
|
||||
msgstr ""
|
||||
|
||||
@@ -4449,17 +4449,17 @@ msgstr ""
|
||||
msgid "Domain"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:892 netbox/dcim/forms/bulk_import.py:1646
|
||||
#: netbox/dcim/forms/bulk_edit.py:892 netbox/dcim/forms/bulk_import.py:1693
|
||||
#: netbox/dcim/forms/filtersets.py:1316 netbox/dcim/forms/model_forms.py:891
|
||||
msgid "Power panel"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:914 netbox/dcim/forms/bulk_import.py:1682
|
||||
#: netbox/dcim/forms/bulk_edit.py:914 netbox/dcim/forms/bulk_import.py:1729
|
||||
#: netbox/dcim/forms/filtersets.py:1338
|
||||
msgid "Supply"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1687
|
||||
#: netbox/dcim/forms/bulk_edit.py:920 netbox/dcim/forms/bulk_import.py:1734
|
||||
#: netbox/dcim/forms/filtersets.py:1343
|
||||
msgid "Phase"
|
||||
msgstr ""
|
||||
@@ -4690,7 +4690,7 @@ msgid "available options"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:149 netbox/dcim/forms/bulk_import.py:643
|
||||
#: netbox/dcim/forms/bulk_import.py:1643 netbox/ipam/forms/bulk_import.py:512
|
||||
#: netbox/dcim/forms/bulk_import.py:1690 netbox/ipam/forms/bulk_import.py:512
|
||||
#: netbox/virtualization/forms/bulk_import.py:64
|
||||
#: netbox/virtualization/forms/bulk_import.py:102
|
||||
msgid "Assigned site"
|
||||
@@ -4753,7 +4753,7 @@ msgstr ""
|
||||
msgid "Parent site"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:359 netbox/dcim/forms/bulk_import.py:1656
|
||||
#: netbox/dcim/forms/bulk_import.py:359 netbox/dcim/forms/bulk_import.py:1703
|
||||
msgid "Rack's location (if any)"
|
||||
msgstr ""
|
||||
|
||||
@@ -4818,7 +4818,7 @@ msgstr ""
|
||||
msgid "Limit platform assignments to this manufacturer"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:576 netbox/dcim/forms/bulk_import.py:1725
|
||||
#: netbox/dcim/forms/bulk_import.py:576 netbox/dcim/forms/bulk_import.py:1772
|
||||
#: netbox/tenancy/forms/bulk_import.py:116
|
||||
msgid "Assigned role"
|
||||
msgstr ""
|
||||
@@ -5021,7 +5021,7 @@ msgid "VDC {vdc} is not assigned to device {device}"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1103 netbox/dcim/forms/bulk_import.py:1121
|
||||
#: netbox/dcim/forms/bulk_import.py:1468
|
||||
#: netbox/dcim/forms/bulk_import.py:1484
|
||||
msgid "Physical medium classification"
|
||||
msgstr ""
|
||||
|
||||
@@ -5118,121 +5118,144 @@ msgstr ""
|
||||
msgid "Side A device"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1413 netbox/dcim/forms/bulk_import.py:1438
|
||||
msgid "Device name"
|
||||
#: netbox/dcim/forms/bulk_import.py:1414 netbox/dcim/forms/bulk_import.py:1447
|
||||
msgid "Device name (for device component terminations)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1416
|
||||
#: netbox/dcim/forms/bulk_import.py:1417
|
||||
msgid "Side A power panel"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1421 netbox/dcim/forms/bulk_import.py:1454
|
||||
msgid "Power panel name (for power feed terminations)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1424
|
||||
msgid "Side A type"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1422
|
||||
#: netbox/dcim/forms/bulk_import.py:1430
|
||||
msgid "Side A name"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1423 netbox/dcim/forms/bulk_import.py:1448
|
||||
#: netbox/dcim/forms/bulk_import.py:1431 netbox/dcim/forms/bulk_import.py:1464
|
||||
msgid "Termination name"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1428
|
||||
#: netbox/dcim/forms/bulk_import.py:1436
|
||||
msgid "Side B site"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1432
|
||||
#: netbox/dcim/forms/bulk_import.py:1440
|
||||
#: netbox/wireless/forms/bulk_import.py:114
|
||||
msgid "Site of parent device B (if any)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1435
|
||||
#: netbox/dcim/forms/bulk_import.py:1443
|
||||
msgid "Side B device"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1441
|
||||
#: netbox/dcim/forms/bulk_import.py:1450
|
||||
msgid "Side B power panel"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1457
|
||||
msgid "Side B type"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1447
|
||||
#: netbox/dcim/forms/bulk_import.py:1463
|
||||
msgid "Side B name"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1456
|
||||
#: netbox/dcim/forms/bulk_import.py:1472
|
||||
#: netbox/templates/dcim/panels/connection.html:60
|
||||
#: netbox/wireless/forms/bulk_import.py:133
|
||||
msgid "Connection status"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1462
|
||||
#: netbox/dcim/forms/bulk_import.py:1478
|
||||
msgid "Cable connection profile"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1487
|
||||
#: netbox/dcim/forms/bulk_import.py:1503
|
||||
msgid "Color name (e.g. \"Red\") or hex code (e.g. \"f44336\")"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1542
|
||||
#: netbox/dcim/forms/bulk_import.py:1564
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Side {side_upper}: {power_panel} {termination_object} is already connected"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1570
|
||||
#, python-brace-format
|
||||
msgid "{side_upper} side termination not found: {power_panel} {name}"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1588
|
||||
#, python-brace-format
|
||||
msgid "Side {side_upper}: {device} {termination_object} is already connected"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1548
|
||||
#: netbox/dcim/forms/bulk_import.py:1594
|
||||
#, python-brace-format
|
||||
msgid "{side_upper} side termination not found: {device} {name}"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1569
|
||||
#: netbox/dcim/forms/bulk_import.py:1616
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"{color} did not match any used color name and was longer than six "
|
||||
"characters: invalid hex."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1594 netbox/dcim/forms/model_forms.py:926
|
||||
#: netbox/dcim/forms/bulk_import.py:1641 netbox/dcim/forms/model_forms.py:926
|
||||
#: netbox/dcim/tables/devices.py:1144
|
||||
#: netbox/templates/dcim/panels/virtual_chassis_members.html:10
|
||||
msgid "Master"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1598
|
||||
#: netbox/dcim/forms/bulk_import.py:1645
|
||||
msgid "Master device"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1615
|
||||
#: netbox/dcim/forms/bulk_import.py:1662
|
||||
msgid "Name of parent site"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1649
|
||||
#: netbox/dcim/forms/bulk_import.py:1696
|
||||
msgid "Upstream power panel"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1679
|
||||
#: netbox/dcim/forms/bulk_import.py:1726
|
||||
msgid "Primary or redundant"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1684
|
||||
#: netbox/dcim/forms/bulk_import.py:1731
|
||||
msgid "Supply type (AC/DC)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1689
|
||||
#: netbox/dcim/forms/bulk_import.py:1736
|
||||
msgid "Single or three-phase"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1739 netbox/dcim/forms/model_forms.py:1901
|
||||
#: netbox/dcim/forms/bulk_import.py:1786 netbox/dcim/forms/model_forms.py:1901
|
||||
#: netbox/dcim/ui/panels.py:110 netbox/dcim/ui/panels.py:354
|
||||
#: netbox/virtualization/ui/panels.py:28
|
||||
msgid "Primary IPv4"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1743
|
||||
#: netbox/dcim/forms/bulk_import.py:1790
|
||||
msgid "IPv4 address with mask, e.g. 1.2.3.4/24"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1746 netbox/dcim/forms/model_forms.py:1910
|
||||
#: netbox/dcim/forms/bulk_import.py:1793 netbox/dcim/forms/model_forms.py:1910
|
||||
#: netbox/dcim/ui/panels.py:115 netbox/dcim/ui/panels.py:359
|
||||
#: netbox/virtualization/ui/panels.py:33
|
||||
msgid "Primary IPv6"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/forms/bulk_import.py:1750
|
||||
#: netbox/dcim/forms/bulk_import.py:1797
|
||||
msgid "IPv6 address with prefix length, e.g. 2001:db8::1/64"
|
||||
msgstr ""
|
||||
|
||||
@@ -9746,23 +9769,23 @@ msgstr ""
|
||||
msgid "subscriptions"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/models/scripts.py:43
|
||||
#: netbox/extras/models/scripts.py:41
|
||||
msgid "is executable"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/models/scripts.py:65
|
||||
#: netbox/extras/models/scripts.py:63
|
||||
msgid "script"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/models/scripts.py:66
|
||||
#: netbox/extras/models/scripts.py:64
|
||||
msgid "scripts"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/models/scripts.py:112
|
||||
#: netbox/extras/models/scripts.py:110
|
||||
msgid "script module"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/models/scripts.py:113
|
||||
#: netbox/extras/models/scripts.py:111
|
||||
msgid "script modules"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ def validate_peppers(peppers):
|
||||
"""
|
||||
Validate the given dictionary of cryptographic peppers for type & sufficient length.
|
||||
"""
|
||||
if type(peppers) is not dict:
|
||||
if not isinstance(peppers, dict):
|
||||
raise ImproperlyConfigured("API_TOKEN_PEPPERS must be a dictionary.")
|
||||
for key, pepper in peppers.items():
|
||||
if type(key) is not int:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
[project]
|
||||
name = "netbox"
|
||||
version = "4.5.7"
|
||||
version = "4.5.8"
|
||||
requires-python = ">=3.12"
|
||||
description = "The premier source of truth powering network automation."
|
||||
readme = "README.md"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
colorama==0.4.6
|
||||
Django==5.2.12
|
||||
Django==5.2.13
|
||||
django-cors-headers==4.9.0
|
||||
django-debug-toolbar==6.3.0
|
||||
django-filter==25.2
|
||||
@@ -10,7 +10,7 @@ django-pglocks==1.0.4
|
||||
django-prometheus==2.4.1
|
||||
django-redis==6.0.0
|
||||
django-rich==2.2.0
|
||||
django-rq==4.0.1
|
||||
django-rq==4.1.0
|
||||
django-storages==1.14.6
|
||||
django-tables2==2.8.0
|
||||
django-taggit==6.1.0
|
||||
@@ -37,7 +37,7 @@ rq==2.7.0
|
||||
social-auth-app-django==5.7.0
|
||||
social-auth-core==4.8.5
|
||||
sorl-thumbnail==13.0.0
|
||||
strawberry-graphql==0.312.2
|
||||
strawberry-graphql==0.314.3
|
||||
strawberry-graphql-django==0.82.1
|
||||
svgwrite==1.4.3
|
||||
tablib==3.9.0
|
||||
|
||||
Reference in New Issue
Block a user