Compare commits

..

4 Commits

22 changed files with 575 additions and 593 deletions

View File

@@ -4,10 +4,17 @@ import { AxiosError } from 'axios';
import { ErrorV2Resp, SuccessResponseV2 } from 'types/api';
import { Pipeline } from 'types/api/pipeline/def';
import { Props } from 'types/api/pipeline/post';
import { toLegacyTagFilter } from 'utils/fieldContext';
const post = async (props: Props): Promise<SuccessResponseV2<Pipeline>> => {
try {
const response = await axios.post('/logs/pipelines', props.data);
const response = await axios.post('/logs/pipelines', {
...props.data,
pipelines: props.data.pipelines.map((pipeline) => ({
...pipeline,
filter: toLegacyTagFilter(pipeline.filter),
})),
});
return {
httpStatusCode: response.status,

View File

@@ -1,6 +1,7 @@
import axios from 'api';
import { ILog } from 'types/api/logs/log';
import { PipelineData } from 'types/api/pipeline/def';
import { toLegacyTagFilter } from 'utils/fieldContext';
export interface PipelineSimulationRequest {
logs: ILog[];
@@ -15,7 +16,13 @@ const simulatePipelineProcessing = async (
requestBody: PipelineSimulationRequest,
): Promise<PipelineSimulationResponse> =>
axios
.post('/logs/pipelines/preview', requestBody)
.post('/logs/pipelines/preview', {
...requestBody,
pipelines: requestBody.pipelines.map((pipeline) => ({
...pipeline,
filter: toLegacyTagFilter(pipeline.filter),
})),
})
.then((res) => res.data.data);
export default simulatePipelineProcessing;

View File

@@ -130,7 +130,7 @@ function CeleryOverviewConfigOptions(): JSX.Element {
{
placeholder: 'Service Name',
queryParam: QueryParams.service,
filterType: 'serviceName',
filterType: 'service.name',
},
{
placeholder: 'Span Name',

View File

@@ -2,22 +2,22 @@ import { useQuery } from 'react-query';
// eslint-disable-next-line no-restricted-imports
import { useSelector } from 'react-redux';
import type { DefaultOptionType } from 'antd/es/select';
import { getAttributesValues } from 'api/queryBuilder/getAttributesValues';
import { DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY } from 'constants/queryBuilder';
import { getFieldValueSuggestions } from 'api/querySuggestions/getFieldValueSuggestions';
import { FIELD_API_CACHE_TIME } from 'constants/queryCacheTime';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import { toFieldValues } from 'hooks/querySuggestions/useFieldValuesSuggestion';
import { AppState } from 'store/reducers';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { DataSource } from 'types/common/queryBuilder';
import { DATA_SOURCE_TO_SIGNAL, DataSource } from 'types/common/queryBuilder';
import { GlobalReducer } from 'types/reducer/globalTime';
import { getValuesForDataType } from 'utils/fieldValues';
export interface Filters {
searchText: string;
attributeKey: string | string[];
aggregateOperator?: string;
dataSource?: DataSource;
aggregateAttribute?: string;
metricName?: string;
filterAttributeKeyDataType?: DataTypes;
tagType?: string;
}
export interface GetAllFiltersResponse {
@@ -29,11 +29,9 @@ export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
const {
searchText,
attributeKey,
aggregateOperator,
dataSource,
aggregateAttribute,
metricName,
filterAttributeKeyDataType,
tagType,
} = props;
const { minTime, maxTime } = useSelector<AppState, GlobalReducer>(
@@ -43,6 +41,8 @@ export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
const { data, isLoading } = useQuery(
[
REACT_QUERY_KEY.GET_ATTRIBUTE_VALUES,
dataSource,
metricName,
attributeKey,
searchText,
minTime,
@@ -53,30 +53,20 @@ export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
const responses = await Promise.all(
keys.map((key) =>
getAttributesValues({
aggregateOperator: aggregateOperator || 'noop',
dataSource: dataSource || DataSource.TRACES,
aggregateAttribute: aggregateAttribute || '',
attributeKey: key,
getFieldValueSuggestions({
signal: DATA_SOURCE_TO_SIGNAL[dataSource || DataSource.TRACES],
name: key,
searchText: searchText ?? '',
filterAttributeKeyDataType:
filterAttributeKeyDataType || DataTypes.String,
tagType: tagType || 'tag',
metricName,
}),
),
);
const uniqueValues = [
...new Set(
responses.flatMap(({ payload }) => {
if (!payload) {
return [];
}
const dataType = filterAttributeKeyDataType || DataTypes.String;
const key = DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY[dataType];
return key ? payload[key] || [] : [];
}),
responses.flatMap((response) =>
getValuesForDataType(toFieldValues(response), filterAttributeKeyDataType),
),
),
];
@@ -85,6 +75,7 @@ export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
value: val,
}));
},
{ staleTime: FIELD_API_CACHE_TIME },
);
return { options: data ?? [], isFetching: isLoading };

View File

@@ -73,11 +73,9 @@ export default function CeleryTaskGraphGrid({
const { options } = useCeleryFilterOptions(
'worker',
'rate',
DataSource.METRICS,
'flower_task_runtime_seconds_sum',
DataTypes.String,
'tag',
);
const isDarkMode = useIsDarkMode();

View File

@@ -8,11 +8,9 @@ import { useGetAllFilters } from './CeleryTaskConfigOptions/useGetCeleryFilters'
export const useCeleryFilterOptions = (
type: string | string[],
aggregateOperator?: string,
dataSource?: DataSource,
aggregateAttribute?: string,
metricName?: string,
filterAttributeKeyDataType?: DataTypes,
tagType?: string,
): {
searchText: string;
handleSearch: (value: string) => void;
@@ -23,11 +21,9 @@ export const useCeleryFilterOptions = (
const { isFetching, options } = useGetAllFilters({
attributeKey: type,
searchText,
aggregateOperator,
dataSource,
aggregateAttribute,
metricName,
filterAttributeKeyDataType,
tagType,
});
const handleDebouncedSearch = useDebouncedFn((searchText): void => {
setSearchText(searchText as string);

View File

@@ -1,6 +1,6 @@
import { TelemetrytypesFieldContextDTO } from 'api/generated/services/sigNoz.schemas';
import { SIGNAL_DATA_SOURCE_MAP } from 'components/QuickFilters/QuickFiltersSettings/constants';
import { TelemetryFieldKey } from 'types/api/v5/queryRange';
import { fieldContextToAttributeType } from 'utils/fieldContext';
import { fieldDataTypeToDataType } from 'utils/fieldDataType';
import { FiltersType, IQuickFiltersConfig, SignalType } from './types';
@@ -15,19 +15,6 @@ const FILTER_TYPE_MAP: Record<string, FiltersType> = {
duration_nano: FiltersType.DURATION,
};
// The map below exists only for the old v3 attribute-values fetch
// (useCheckboxFilterValues), the sole reader of attributeKey.dataType/type.
// Once the values fetch moves to fields/values, remove this and reduce
// attributeKey to { id, key }.
const FIELD_CONTEXT_TO_ATTRIBUTE_TYPE: Record<string, string> = {
[TelemetrytypesFieldContextDTO.attribute]: 'tag',
[TelemetrytypesFieldContextDTO.resource]: 'resource',
};
const mapFieldContext = (fieldContext?: string): string =>
(fieldContext && FIELD_CONTEXT_TO_ATTRIBUTE_TYPE[fieldContext]) || '';
const getFilterName = (str: string): string => {
if (FILTER_TITLE_MAP[str]) {
return FILTER_TITLE_MAP[str];
@@ -64,11 +51,15 @@ export const getFilterConfig = (
type: getFilterType(att),
title: getFilterName(att.name),
dataSource: SIGNAL_DATA_SOURCE_MAP[signal],
// The type mapping below exists only for the old v3 attribute-values fetch
// (useCheckboxFilterValues), the sole reader of attributeKey.dataType/type.
// Once the values fetch moves to fields/values, remove this and reduce
// attributeKey to { id, key }.
attributeKey: {
id: att.name,
key: att.name,
dataType: fieldDataTypeToDataType(att.fieldDataType),
type: mapFieldContext(att.fieldContext),
type: fieldContextToAttributeType(att.fieldContext),
},
defaultOpen: index < 2,
}) as IQuickFiltersConfig,

View File

@@ -10,7 +10,6 @@ import {
userEvent,
waitFor,
} from 'tests/test-utils';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { pipelineApiResponseMockData } from '../mocks/pipeline';
import PipelineListsView from '../PipelineListsView';
@@ -85,7 +84,7 @@ jest.mock('providers/preferences/sync/usePreferenceSync', () => ({
}));
const BASE_URL = ENVIRONMENT.baseURL;
const attributeKeysURL = `${BASE_URL}/api/v3/filter_suggestions`;
const fieldKeysURL = `${BASE_URL}/api/v1/fields/keys`;
describe('PipelinePage container test', () => {
beforeAll(() => {
@@ -339,42 +338,41 @@ describe('PipelinePage container test', () => {
expect(screen.queryAllByText('source = nginx')).toHaveLength(2);
server.use(
rest.get(attributeKeysURL, (_req, res, ctx) =>
rest.get(fieldKeysURL, (_req, res, ctx) =>
res(
ctx.status(200),
ctx.json({
status: 'success',
data: {
attributes: [
{
key: 'otelServiceName',
dataType: DataTypes.String,
type: 'tag',
isColumn: false,
isJSON: false,
},
{
key: 'service.name',
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
},
{
key: 'service.instance.id',
dataType: DataTypes.String,
type: 'resource',
isColumn: false,
isJSON: false,
},
{
key: 'service.name',
dataType: DataTypes.String,
type: 'tag',
isColumn: false,
isJSON: false,
},
],
complete: true,
keys: {
otelServiceName: [
{
name: 'otelServiceName',
fieldContext: 'attribute',
fieldDataType: 'string',
},
],
'service.name': [
{
name: 'service.name',
fieldContext: 'resource',
fieldDataType: 'string',
},
{
name: 'service.name',
fieldContext: 'attribute',
fieldDataType: 'string',
},
],
'service.instance.id': [
{
name: 'service.instance.id',
fieldContext: 'resource',
fieldDataType: 'string',
},
],
},
},
}),
),

View File

@@ -12,7 +12,6 @@ import { Select, Spin } from 'antd';
import { Pill } from '@signozhq/ui/pill';
import cx from 'classnames';
import {
DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY,
OperatorConfigKeys,
OPERATORS,
QUERY_BUILDER_OPERATORS_BY_TYPES,
@@ -22,23 +21,14 @@ import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig';
import { LogsExplorerShortcuts } from 'constants/shortcuts/logsExplorerShortcuts';
import { useDynamicVariableSuggestions } from 'hooks/dashboard/useDynamicVariableSuggestions';
import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys';
import { useGetAggregateKeys } from 'hooks/queryBuilder/useGetAggregateKeys';
import { useGetAggregateValues } from 'hooks/queryBuilder/useGetAggregateValues';
import { useGetAttributeSuggestions } from 'hooks/queryBuilder/useGetAttributeSuggestions';
import { validationMapper } from 'hooks/queryBuilder/useIsValidTag';
import { operatorTypeMapper } from 'hooks/queryBuilder/useOperatorType';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useRunQueryWithFilterItems } from 'hooks/queryBuilder/useRunQueryWithFilterItems';
import { useFieldKeysSuggestion } from 'hooks/querySuggestions/useFieldKeysSuggestion';
import { useFieldValuesSuggestion } from 'hooks/querySuggestions/useFieldValuesSuggestion';
import useDebounceValue from 'hooks/useDebounce';
import {
cloneDeep,
isArray,
isEmpty,
isEqual,
isObject,
isUndefined,
unset,
} from 'lodash-es';
import { isArray, isEmpty, isEqual, isObject, isUndefined } from 'lodash-es';
import { ChevronDown, ChevronUp } from '@signozhq/icons';
import type { BaseSelectRef } from 'rc-select';
import {
@@ -49,7 +39,13 @@ import {
IBuilderQuery,
TagFilter,
} from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import {
DATA_SOURCE_TO_SIGNAL,
DataSource,
QUERY_SOURCE_TO_FIELD_SOURCE,
} from 'types/common/queryBuilder';
import { attributeTypeToFieldContext } from 'utils/fieldContext';
import { getValuesForDataType } from 'utils/fieldValues';
import { useSelectPopupContainer } from 'utils/selectPopupContainer';
import { v4 as uuid } from 'uuid';
@@ -62,7 +58,8 @@ import {
getTagToken,
isInNInOperator,
} from './utils';
import { filterByOperatorConfig } from '../utils';
import { toAttributeKey } from '../GroupByFilter/utils';
import { filterByOperatorConfig, getMetricNameForQuery } from '../utils';
import QueryBuilderSearchDropdown from './QueryBuilderSearchDropdown';
import SpanScopeSelector from './SpanScopeSelector';
import Suggestions from './Suggestions';
@@ -187,70 +184,15 @@ function QueryBuilderSearchV2(
[query.dataSource],
);
const memoizedSearchParams = useMemo(
() => [
searchValue,
query.dataSource,
query.aggregateOperator,
query.aggregateAttribute?.key,
],
[
searchValue,
query.dataSource,
query.aggregateOperator,
query.aggregateAttribute?.key,
],
);
const queryFiltersWithoutId = useMemo(
() => ({
...query.filters,
items: query.filters?.items.map((item) => {
const filterWithoutId = cloneDeep(item);
unset(filterWithoutId, 'id');
return filterWithoutId;
}),
}),
[query.filters],
);
const memoizedSuggestionsParams = useMemo(
() => [searchValue, query.dataSource, queryFiltersWithoutId],
[query.dataSource, queryFiltersWithoutId, searchValue],
);
const memoizedValueParams = useMemo(
() => [
query.aggregateOperator,
query.dataSource,
query.aggregateAttribute?.key,
currentFilterItem?.key?.key || '',
currentFilterItem?.key?.dataType,
currentFilterItem?.key?.type ?? '',
isArray(currentFilterItem?.value)
? currentFilterItem?.value?.[currentFilterItem.value.length - 1]
: currentFilterItem?.value,
],
[
query.aggregateOperator,
query.dataSource,
query.aggregateAttribute?.key,
currentFilterItem?.key?.key,
currentFilterItem?.key?.dataType,
currentFilterItem?.key?.type,
currentFilterItem?.value,
],
);
const searchParams = useDebounceValue(memoizedSearchParams, DEBOUNCE_DELAY);
const valueParams = useDebounceValue(memoizedValueParams, DEBOUNCE_DELAY);
const suggestionsParams = useDebounceValue(
memoizedSuggestionsParams,
const debouncedKeySearchText = useDebounceValue(
searchValue?.split(' ')[0] ?? '',
DEBOUNCE_DELAY,
);
const valueSearchText = isArray(currentFilterItem?.value)
? String(currentFilterItem?.value?.[currentFilterItem.value.length - 1] ?? '')
: currentFilterItem?.value?.toString() || '';
const isQueryEnabled = useMemo(() => {
if (currentState === DropdownState.ATTRIBUTE_KEY) {
return query.dataSource === DataSource.METRICS
@@ -263,53 +205,58 @@ function QueryBuilderSearchV2(
const dashboardDynamicVariables = useDynamicVariableSuggestions();
const { data, isFetching } = useGetAggregateKeys(
const signal = DATA_SOURCE_TO_SIGNAL[query.dataSource];
const source = QUERY_SOURCE_TO_FIELD_SOURCE[query.source ?? ''];
const metricName = getMetricNameForQuery(query);
const { data: fieldKeys, isFetching } = useFieldKeysSuggestion(
{
searchText: searchValue?.split(' ')[0],
dataSource: query.dataSource,
aggregateOperator: query.aggregateOperator || '',
aggregateAttribute: query.aggregateAttribute?.key || '',
tagType: query.aggregateAttribute?.type ?? null,
signal,
source,
metricName,
fieldContext: attributeTypeToFieldContext(query.aggregateAttribute?.type),
searchText: debouncedKeySearchText,
},
query.builderQueryType,
{
queryKey: [searchParams],
enabled: isQueryEnabled && !isLogsDataSource && !hardcodedAttributeKeys,
enabled: isQueryEnabled && !hardcodedAttributeKeys,
keepPreviousData: true,
},
);
const { data: suggestionsData, isFetching: isFetchingSuggestions } =
useGetAttributeSuggestions(
{
searchText: searchValue?.split(' ')[0],
dataSource: query.dataSource,
filters: query.filters || { items: [], op: 'AND' },
},
{
queryKey: [suggestionsParams],
enabled: isQueryEnabled && isLogsDataSource,
},
);
const attributeKeys = useMemo(
() => (fieldKeys ?? []).map(toAttributeKey),
[fieldKeys],
);
const { data: attributeValues, isFetching: isFetchingAttributeValues } =
useGetAggregateValues(
{
aggregateOperator: query.aggregateOperator || '',
dataSource: query.dataSource,
aggregateAttribute: query.aggregateAttribute?.key || '',
attributeKey: currentFilterItem?.key?.key || '',
filterAttributeKeyDataType:
currentFilterItem?.key?.dataType ?? DataTypes.EMPTY,
tagType: currentFilterItem?.key?.type ?? '',
searchText: isArray(currentFilterItem?.value)
? String(currentFilterItem?.value?.[currentFilterItem.value.length - 1]) ||
''
: currentFilterItem?.value?.toString() || '',
},
{
enabled: currentState === DropdownState.ATTRIBUTE_VALUE,
queryKey: [valueParams],
},
);
const fieldValuesConfig = useMemo(
() => ({
signal,
source,
metricName,
name: currentFilterItem?.key?.key || '',
fieldContext: attributeTypeToFieldContext(currentFilterItem?.key?.type),
searchText: valueSearchText,
}),
[
signal,
source,
metricName,
currentFilterItem?.key?.key,
currentFilterItem?.key?.type,
valueSearchText,
],
);
const debouncedFieldValuesConfig = useDebounceValue(
fieldValuesConfig,
DEBOUNCE_DELAY,
);
const { data: fieldValues, isFetching: isFetchingAttributeValues } =
useFieldValuesSuggestion(debouncedFieldValuesConfig, query.builderQueryType, {
enabled: currentState === DropdownState.ATTRIBUTE_VALUE,
});
const handleDropdownSelect = useCallback(
(value: string) => {
@@ -534,15 +481,13 @@ function QueryBuilderSearchV2(
if (tagKey && isUndefined(currentFilterItem?.key)) {
let currentRunningAttributeKey;
const isSuggestedKeyInAutocomplete =
suggestionsData?.payload?.attributes?.some(
(value) => value.key === tagKey.split(' ')[0],
);
isLogsDataSource &&
attributeKeys.some((value) => value.key === tagKey.split(' ')[0]);
if (isSuggestedKeyInAutocomplete) {
const allAttributesMatchingTheKey =
suggestionsData?.payload?.attributes?.filter(
(value) => value.key === tagKey.split(' ')[0],
) || [];
const allAttributesMatchingTheKey = attributeKeys.filter(
(value) => value.key === tagKey.split(' ')[0],
);
if (allAttributesMatchingTheKey?.length === 1) {
[currentRunningAttributeKey] = allAttributesMatchingTheKey;
@@ -649,9 +594,10 @@ function QueryBuilderSearchV2(
currentFilterItem,
currentFilterItem?.key,
currentFilterItem?.op,
suggestionsData?.payload?.attributes,
attributeKeys,
isLogsDataSource,
searchValue,
isFetchingSuggestions,
isFetching,
currentState,
]);
@@ -663,9 +609,7 @@ function QueryBuilderSearchV2(
// add the user typed option in the dropdown to select that and move ahead irrespective of the matches and all
setDropdownOptions([
...(!isEmpty(tagKey) &&
!suggestionsData?.payload?.attributes?.some((val) =>
isEqual(val.key, tagKey),
)
!attributeKeys.some((val) => isEqual(val.key, tagKey))
? [
{
label: tagKey,
@@ -677,10 +621,10 @@ function QueryBuilderSearchV2(
},
]
: []),
...(suggestionsData?.payload?.attributes?.map((key) => ({
...attributeKeys.map((key) => ({
label: key.key,
value: key,
})) || []),
})),
]);
} else if (hardcodedAttributeKeys) {
const filteredKeys = hardcodedAttributeKeys.filter((key) =>
@@ -698,7 +642,7 @@ function QueryBuilderSearchV2(
setDropdownOptions([
// Add user typed option if it doesn't exist in the payload
...(tagKey.trim().length > 0 &&
!data?.payload?.attributeKeys?.some((val) => val.key === tagKey)
!attributeKeys.some((val) => val.key === tagKey)
? [
{
label: tagKey,
@@ -711,10 +655,10 @@ function QueryBuilderSearchV2(
]
: []),
// Map existing attribute keys from payload
...(data?.payload?.attributeKeys?.map((key) => ({
...attributeKeys.map((key) => ({
label: key.key,
value: key,
})) || []),
})),
]);
}
}
@@ -779,10 +723,10 @@ function QueryBuilderSearchV2(
values.push(tagValue);
}
if (attributeValues?.payload) {
const dataType = currentFilterItem?.key?.dataType || DataTypes.String;
const key = DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY[dataType];
values.push(...(attributeValues?.payload?.[key] || []));
if (fieldValues) {
values.push(
...getValuesForDataType(fieldValues, currentFilterItem?.key?.dataType),
);
// here we want to suggest the variable name matching with the key here, we will go over the dynamic variables for the keys
const variableName = dashboardDynamicVariables.find(
@@ -806,13 +750,12 @@ function QueryBuilderSearchV2(
}
}, [
hardcodedAttributeKeys,
attributeValues?.payload,
fieldValues,
currentFilterItem?.key?.dataType,
currentState,
data?.payload?.attributeKeys,
attributeKeys,
isLogsDataSource,
searchValue,
suggestionsData?.payload?.attributes,
operatorConfigKey,
currentFilterItem?.key?.key,
dashboardDynamicVariables,
@@ -881,8 +824,8 @@ function QueryBuilderSearchV2(
}, [deregisterShortcut, isLastQuery, registerShortcut]);
const loading = useMemo(
() => isFetching || isFetchingAttributeValues || isFetchingSuggestions,
[isFetching, isFetchingAttributeValues, isFetchingSuggestions],
() => isFetching || isFetchingAttributeValues,
[isFetching, isFetchingAttributeValues],
);
const isMetricsDataSource = useMemo(
@@ -992,7 +935,7 @@ function QueryBuilderSearchV2(
setTags((prev) => [...prev, ...(val.items as ITag[])]);
}}
searchValue={searchValue}
exampleQueries={suggestionsData?.payload?.example_queries || []}
exampleQueries={[]}
tags={tags}
currentFilterItem={currentFilterItem}
isLogsDataSource={isLogsDataSource}

View File

@@ -6,8 +6,9 @@ import {
initialQueryBuilderFormValues,
} from 'constants/queryBuilder';
import { DynamicVariableSuggestion } from 'providers/Dashboard/store/dynamicVariableSuggestions';
import { useFieldKeysSuggestion } from 'hooks/querySuggestions/useFieldKeysSuggestion';
import { QueryBuilderContext } from 'providers/QueryBuilder';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { FieldDataType, TelemetryFieldKey } from 'types/api/v5/queryRange';
import { DataSource } from 'types/common/queryBuilder';
import QueryBuilderSearchV2 from '../QueryBuilderSearchV2';
@@ -88,57 +89,31 @@ const renderWithContext = (props = {}): RenderResult => {
const getSearchCombobox = (): HTMLElement =>
within(screen.getByTestId('qb-search-select')).getByRole('combobox');
// Constants to fix linter errors
const TYPE_TAG = 'tag';
const IS_COLUMN_FALSE = false;
const IS_JSON_FALSE = false;
const mockAggregateKeysData = {
payload: {
attributeKeys: [
{
key: 'http.status',
dataType: DataTypes.String,
type: TYPE_TAG,
id: 'http.status--string--tag--false',
},
{
key: 'service.name',
dataType: DataTypes.String,
type: TYPE_TAG,
isColumn: IS_COLUMN_FALSE,
isJSON: IS_JSON_FALSE,
id: 'service.name--string--tag--false',
},
{
key: 'unmapped.attribute',
dataType: 'not-a-real-data-type' as unknown as DataTypes,
type: TYPE_TAG,
isColumn: IS_COLUMN_FALSE,
isJSON: IS_JSON_FALSE,
id: 'unmapped.attribute--String--tag--false',
},
],
const mockFieldKeys: TelemetryFieldKey[] = [
{ name: 'http.status', fieldContext: 'attribute', fieldDataType: 'string' },
{ name: 'service.name', fieldContext: 'attribute', fieldDataType: 'string' },
{
name: 'unmapped.attribute',
fieldContext: 'attribute',
fieldDataType: 'not-a-real-data-type' as FieldDataType,
},
};
];
jest.mock('hooks/queryBuilder/useGetAggregateKeys', () => ({
useGetAggregateKeys: jest.fn(() => ({
data: mockAggregateKeysData,
jest.mock('hooks/querySuggestions/useFieldKeysSuggestion', () => ({
useFieldKeysSuggestion: jest.fn(() => ({
data: mockFieldKeys,
isFetching: false,
})),
}));
const mockAggregateValuesData = {
payload: {
stringAttributeValues: ['200', '404', '500'],
numberAttributeValues: [200, 404, 500],
},
const mockFieldValues = {
stringValues: ['200', '404', '500'],
numberValues: [200, 404, 500],
};
jest.mock('hooks/queryBuilder/useGetAggregateValues', () => ({
useGetAggregateValues: jest.fn(() => ({
data: mockAggregateValuesData,
jest.mock('hooks/querySuggestions/useFieldValuesSuggestion', () => ({
useFieldValuesSuggestion: jest.fn(() => ({
data: mockFieldValues,
isFetching: false,
})),
}));
@@ -196,7 +171,11 @@ describe('Suggestion Key -> Operator -> Value Flow', () => {
expect.objectContaining({
items: expect.arrayContaining([
expect.objectContaining({
key: expect.objectContaining({ key: 'http.status' }),
key: expect.objectContaining({
key: 'http.status',
type: 'attribute',
dataType: 'string',
}),
op: '=',
value: '200',
}),
@@ -279,3 +258,33 @@ describe('Dynamic Variable Suggestions', () => {
);
});
});
describe('Key fetch context', () => {
it('limits keys to the aggregate attribute context, as the resource filter needs', () => {
renderWithContext({
query: {
...defaultProps.query,
aggregateAttribute: {
...defaultProps.query.aggregateAttribute,
type: 'resource',
},
},
});
expect(useFieldKeysSuggestion).toHaveBeenLastCalledWith(
expect.objectContaining({ fieldContext: 'resource' }),
undefined,
expect.anything(),
);
});
it('fetches keys from every context when the aggregate attribute has no type', () => {
renderWithContext();
expect(useFieldKeysSuggestion).toHaveBeenLastCalledWith(
expect.objectContaining({ fieldContext: undefined }),
undefined,
expect.anything(),
);
});
});

View File

@@ -24,7 +24,6 @@ import { fieldValuesResponse } from '@/storybook/msw/__story_mockdata__/fields';
import {
EXCEPTION_CATALOGUE_SIZE,
EXCEPTION_QUICK_FILTER_CAP,
exceptionAttributeKeysResponse,
exceptionAttributeValuesResponse,
exceptionFieldKeysResponse,
exceptionQuickFiltersResponse,
@@ -58,7 +57,7 @@ export const exceptionsMocks = defineStoryMocks({
filterKeys: choiceControl<ResponseState>('Filter keys', {
group: FILTERS,
description:
'How `/autocomplete/attribute_keys` answers when the resource filter opens, apart from the page-wide Data control.',
'How `/fields/keys` answers when the resource filter opens, apart from the page-wide Data control.',
options: RESPONSE_STATES,
value: 'loaded',
}),
@@ -95,7 +94,7 @@ export const exceptionsMocks = defineStoryMocks({
rest.get(
'http://localhost/api/v1/fields/keys',
response.json((req) =>
respondWith(values.filterKeys, (req) =>
exceptionFieldKeysResponse(req.url.searchParams.get('searchText')),
),
),
@@ -109,23 +108,6 @@ export const exceptionsMocks = defineStoryMocks({
),
),
),
rest.get(
'http://localhost/api/v3/autocomplete/attribute_keys',
respondWith(values.filterKeys, (req) =>
exceptionAttributeKeysResponse(req.url.searchParams.get('searchText')),
),
),
rest.get(
'http://localhost/api/v3/autocomplete/attribute_values',
response.json((req) =>
exceptionAttributeValuesResponse(
req.url.searchParams.get('attributeKey'),
req.url.searchParams.get('searchText'),
),
),
),
],
effect: (values) => {
set(LOCALSTORAGE.SHOW_EXCEPTIONS_QUICK_FILTERS, String(values.filterPanel));

View File

@@ -17,7 +17,6 @@ import type {
import {
type BaseAutocompleteData,
DataTypes,
type IQueryAutocompleteResponse,
} from 'types/api/queryBuilder/queryAutocompleteResponse';
import type { Exception, Order, OrderBy } from 'types/api/errors/getAll';
import type { IAttributeValuesResponse } from 'types/api/queryBuilder/getAttributesValues';
@@ -311,21 +310,6 @@ const ATTRIBUTE_KEYS: BaseAutocompleteData[] = [
{ key: 'cloud.region', dataType: DataTypes.String, type: 'resource' },
];
export const exceptionAttributeKeysResponse = (
searchText: string | null,
): { status: string; data: IQueryAutocompleteResponse } => {
const search = (searchText ?? '').toLowerCase();
return {
status: 'success',
data: {
attributeKeys: ATTRIBUTE_KEYS.filter(({ key }) =>
key.toLowerCase().includes(search),
),
},
};
};
/** The quick filter settings panel lists its "other filters" from `/fields/keys`. */
export const exceptionFieldKeysResponse = (
searchText: string | null,

View File

@@ -9,6 +9,7 @@ import type { QueryRangePayload } from 'types/api/metrics/getQueryRange';
import { choiceControl, countControl } from '@/storybook/controls/controls';
import { defineStoryMocks } from '@/storybook/controls/defineStoryMocks';
import { fieldValuesResponse } from '@/storybook/msw/__story_mockdata__/fields';
import {
attributeValuesResponse,
@@ -77,28 +78,18 @@ export const celeryTaskMocks = defineStoryMocks({
rest.post('http://localhost/api/v4/query_range', queryRange),
rest.get(
'http://localhost/api/v3/autocomplete/attribute_values',
'http://localhost/api/v1/fields/values',
response.json((req) => {
const attributeKey = req.url.searchParams.get('attributeKey') ?? '';
const values_ = attributeValuesResponse(
attributeKey,
req.url.searchParams.get('searchText') ?? '',
const name = req.url.searchParams.get('name') ?? '';
const found =
attributeValuesResponse(
name,
req.url.searchParams.get('searchText') ?? '',
).data.stringAttributeValues ?? [];
return fieldValuesResponse(
name === 'worker' ? found.slice(0, values.workers) : found,
);
if (attributeKey !== 'worker') {
return values_;
}
return {
...values_,
data: {
...values_.data,
stringAttributeValues: (values_.data.stringAttributeValues ?? []).slice(
0,
values.workers,
),
},
};
}),
),
];

View File

@@ -13,6 +13,7 @@ import {
toggleControl,
} from '@/storybook/controls/controls';
import { defineStoryMocks } from '@/storybook/controls/defineStoryMocks';
import { fieldValuesResponse } from '@/storybook/msw/__story_mockdata__/fields';
import {
attributeValuesResponse,
@@ -91,11 +92,13 @@ export const queueOverviewMocks = defineStoryMocks({
rest.post('http://localhost/api/v4/query_range', queryRange),
rest.get(
'http://localhost/api/v3/autocomplete/attribute_values',
'http://localhost/api/v1/fields/values',
response.json((req) =>
attributeValuesResponse(
req.url.searchParams.get('attributeKey') ?? '',
req.url.searchParams.get('searchText') ?? '',
fieldValuesResponse(
attributeValuesResponse(
req.url.searchParams.get('name') ?? '',
req.url.searchParams.get('searchText') ?? '',
).data.stringAttributeValues ?? [],
),
),
),

View File

@@ -82,15 +82,15 @@ const CELERY_TASKS = [
const CELERY_WORKERS = ['worker-a', 'worker-b', 'worker-c'];
/**
* Values per autocomplete attribute key. The kafka config selects and both
* celery filter rows read the same v3 endpoint, so one map answers for all of
* Values per attribute key. The kafka config selects read the v3 endpoint and
* the celery filter rows read `/fields/values`, so one map answers for all of
* them; a key nobody seeded answers empty rather than 501.
*/
const ATTRIBUTE_VALUES: Record<string, string[]> = {
group: CONSUMER_GROUPS,
topic: TOPICS,
partition: PARTITIONS,
serviceName: KAFKA_SERVICES,
'service.name': KAFKA_SERVICES,
name: [
'order-events send',
'order-events process',

View File

@@ -145,7 +145,7 @@ function FunnelStep({
<FilterSelect
placeholder="Select Service"
queryParam={QueryParams.service}
filterType="serviceName"
filterType="service.name"
shouldSetQueryParams={false}
values={stepData.service_name}
isMultiple={false}

View File

@@ -3,15 +3,19 @@
* Do not hand-edit: regenerate instead.
*/
import {
TelemetrytypesFieldContextDTO,
TelemetrytypesSignalDTO,
} from 'api/generated/services/sigNoz.schemas';
import ROUTES from 'constants/routes';
import { rest } from 'msw';
import { choiceControl, countControl } from '@/storybook/controls/controls';
import { defineStoryMocks } from '@/storybook/controls/defineStoryMocks';
import {
attributeKeysResponse,
attributeValuesResponse,
} from '@/storybook/msw/__story_mockdata__/attributes';
fieldKeysResponse,
fieldValuesResponse,
} from '@/storybook/msw/__story_mockdata__/fields';
import {
FUNNEL_ID,
@@ -41,13 +45,9 @@ const CONVERSION: Record<DropOff, number> = {
const ENTERED = 24_000;
const STEP_FILTER_KEYS = [
'service.name',
'name',
'http.status_code',
'deployment.environment',
'hasError',
];
const STEP_RESOURCE_KEYS = ['service.name', 'deployment.environment'];
const STEP_ATTRIBUTE_KEYS = ['name', 'http.status_code', 'hasError'];
const STEP_FILTER_VALUES: Record<string, string[]> = {
'service.name': ['frontend', 'checkout', 'payment', 'shipping'],
@@ -115,20 +115,44 @@ export const tracesFunnelDetailsMocks = defineStoryMocks({
'http://localhost/api/v1/trace-funnels/analytics/error-traces',
response.json(() => funnelErrorTracesResponse(values.traces)),
),
// The `Where` box on every step is the trace query builder, which reads
// its suggestions as soon as the step renders.
// The `Where` box on every step reads its suggestions as soon as the step
// renders, and the service and span name selects read `service.name` and
// `name` from the same values endpoint.
rest.get(
'http://localhost/api/v3/autocomplete/attribute_keys',
response.json(() => attributeKeysResponse(STEP_FILTER_KEYS)),
'http://localhost/api/v1/fields/keys',
response.json(() => {
const signal = TelemetrytypesSignalDTO.traces;
const resource = fieldKeysResponse(STEP_RESOURCE_KEYS, {
signal,
fieldContext: TelemetrytypesFieldContextDTO.resource,
});
const attribute = fieldKeysResponse(STEP_ATTRIBUTE_KEYS, {
signal,
fieldContext: TelemetrytypesFieldContextDTO.attribute,
});
return {
...resource,
data: {
...resource.data,
keys: { ...resource.data.keys, ...attribute.data.keys },
},
};
}),
),
rest.get(
'http://localhost/api/v3/autocomplete/attribute_values',
response.json((req) =>
attributeValuesResponse(
STEP_FILTER_VALUES[req.url.searchParams.get('attributeKey') ?? ''] ?? [],
req.url.searchParams.get('searchText') ?? '',
),
),
'http://localhost/api/v1/fields/values',
response.json((req) => {
const searchText = (
req.url.searchParams.get('searchText') ?? ''
).toLowerCase();
return fieldValuesResponse(
(STEP_FILTER_VALUES[req.url.searchParams.get('name') ?? ''] ?? []).filter(
(value) => value.toLowerCase().includes(searchText),
),
);
}),
),
];
},

View File

@@ -0,0 +1,30 @@
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
import { toLegacyTagFilter } from '../fieldContext';
const item = (type: string): TagFilter['items'][number] => ({
id: type,
key: { key: 'k', dataType: DataTypes.String, type },
op: '=',
value: 'v',
});
describe('toLegacyTagFilter', () => {
it('sends attribute keys as tag and leaves every other type as is', () => {
const filter: TagFilter = {
op: 'AND',
items: [
item('attribute'),
item('resource'),
item('tag'),
item(''),
item('spanSearchScope'),
],
};
expect(toLegacyTagFilter(filter).items.map((i) => i.key?.type)).toStrictEqual(
['tag', 'resource', 'tag', '', 'spanSearchScope'],
);
});
});

View File

@@ -0,0 +1,37 @@
import { TelemetrytypesFieldContextDTO } from 'api/generated/services/sigNoz.schemas';
import type { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
// Legacy filter builders read `tag` / `resource`; any other context is a top-level field there.
const FIELD_CONTEXT_TO_ATTRIBUTE_TYPE: Record<string, string> = {
[TelemetrytypesFieldContextDTO.attribute]: 'tag',
[TelemetrytypesFieldContextDTO.resource]: 'resource',
};
const ATTRIBUTE_TYPE_TO_FIELD_CONTEXT: Record<
string,
TelemetrytypesFieldContextDTO
> = {
tag: TelemetrytypesFieldContextDTO.attribute,
attribute: TelemetrytypesFieldContextDTO.attribute,
resource: TelemetrytypesFieldContextDTO.resource,
};
export const fieldContextToAttributeType = (fieldContext?: string): string =>
(fieldContext && FIELD_CONTEXT_TO_ATTRIBUTE_TYPE[fieldContext]) || '';
export const attributeTypeToFieldContext = (
type?: string | null,
): TelemetrytypesFieldContextDTO | undefined =>
type ? ATTRIBUTE_TYPE_TO_FIELD_CONTEXT[type] : undefined;
export const toLegacyTagFilter = (filter: TagFilter): TagFilter =>
filter && {
...filter,
items: (filter.items ?? []).map((item) => ({
...item,
key: item.key && {
...item.key,
type: FIELD_CONTEXT_TO_ATTRIBUTE_TYPE[item.key.type ?? ''] ?? item.key.type,
},
})),
};

View File

@@ -0,0 +1,21 @@
import { TelemetrytypesTelemetryFieldValuesDTO } from 'api/generated/services/sigNoz.schemas';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
// Numbers and bools stay raw so tags keep their value type.
export const getValuesForDataType = (
values: TelemetrytypesTelemetryFieldValuesDTO | undefined,
dataType: DataTypes | undefined,
): string[] => {
switch (dataType) {
case DataTypes.Int64:
case DataTypes.Float64:
case DataTypes.ArrayInt64:
case DataTypes.ArrayFloat64:
return (values?.numberValues ?? []) as unknown as string[];
case DataTypes.bool:
case DataTypes.ArrayBool:
return (values?.boolValues ?? []) as unknown as string[];
default:
return values?.stringValues ?? [];
}
};

View File

@@ -42,9 +42,9 @@
"@types/node": "^20.0.0",
"dotenv": "^16.0.0",
"eslint-plugin-playwright": "^2.10.2",
"oxfmt": "0.73.0",
"oxlint": "1.88.0",
"oxlint-tsgolint": "7.0.2004",
"oxfmt": "^0.41.0",
"oxlint": "^1.59.0",
"oxlint-tsgolint": "^0.20.0",
"typescript": "^5.0.0"
},
"engines": {

434
tests/e2e/pnpm-lock.yaml generated
View File

@@ -24,14 +24,14 @@ importers:
specifier: ^2.10.2
version: 2.10.2(eslint@10.2.1)
oxfmt:
specifier: 0.73.0
version: 0.73.0
specifier: ^0.41.0
version: 0.41.0
oxlint:
specifier: 1.88.0
version: 1.88.0(oxlint-tsgolint@7.0.2004)
specifier: ^1.59.0
version: 1.61.0(oxlint-tsgolint@0.20.0)
oxlint-tsgolint:
specifier: 7.0.2004
version: 7.0.2004
specifier: ^0.20.0
version: 0.20.0
typescript:
specifier: ^5.0.0
version: 5.9.3
@@ -88,276 +88,260 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
'@oxfmt/binding-android-arm-eabi@0.73.0':
resolution: {integrity: sha512-dhunAdMbi/4o0Y66/+Wl6rpsNqpvE4i26Qw6bB77A97L2lJoktWg6m+X9QOon8iOEEqzD9rEZqFi5uZ4oIzhCA==}
'@oxfmt/binding-android-arm-eabi@0.41.0':
resolution: {integrity: sha512-REfrqeMKGkfMP+m/ScX4f5jJBSmVNYcpoDF8vP8f8eYPDuPGZmzp56NIUsYmx3h7f6NzC6cE3gqh8GDWrJHCKw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
'@oxfmt/binding-android-arm64@0.73.0':
resolution: {integrity: sha512-dBoypjC2/xeyKyIhN2waX0/XeoccH9k0lVVe+sGRc4X8HSJVRtqyZDoXdr7bGY9A75c51dX0z0dLDpGQKwCdCg==}
'@oxfmt/binding-android-arm64@0.41.0':
resolution: {integrity: sha512-s0b1dxNgb2KomspFV2LfogC2XtSJB42POXF4bMCLJyvQmAGos4ZtjGPfQreToQEaY0FQFjz3030ggI36rF1q5g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@oxfmt/binding-darwin-arm64@0.73.0':
resolution: {integrity: sha512-Tn7Y+qWIpCQK+qdYwBcn6YvqeBuPiuG3tcNlYg16a5QL2o3rSmrgBB1nCyYqo0uvc1LNrfQW9/CK2tzFuID/Fg==}
'@oxfmt/binding-darwin-arm64@0.41.0':
resolution: {integrity: sha512-EGXGualADbv/ZmamE7/2DbsrYmjoPlAmHEpTL4vapLF4EfVD6fr8/uQDFnPJkUBjiSWFJZtFNsGeN1B6V3owmA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@oxfmt/binding-darwin-x64@0.73.0':
resolution: {integrity: sha512-yVb0E0tg/+9Xc9YJCBq66qF1DC/aN5mhb5nnHz0k4ikwkMANtSul2VPDSwjYdXR6/DFimc+pPUgLBqkIa5Ctuw==}
'@oxfmt/binding-darwin-x64@0.41.0':
resolution: {integrity: sha512-WxySJEvdQQYMmyvISH3qDpTvoS0ebnIP63IMxLLWowJyPp/AAH0hdWtlo+iGNK5y3eVfa5jZguwNaQkDKWpGSw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@oxfmt/binding-freebsd-x64@0.73.0':
resolution: {integrity: sha512-IKR4lFnBkYNL9Uqdxa5GMTQLvnLj+3sDwTvh2atHCzah0xeo+1xR5bigRU8uyXlOsA4VpXUn0UAimq4E4RBGmQ==}
'@oxfmt/binding-freebsd-x64@0.41.0':
resolution: {integrity: sha512-Y2kzMkv3U3oyuYaR4wTfGjOTYTXiFC/hXmG0yVASKkbh02BJkvD98Ij8bIevr45hNZ0DmZEgqiXF+9buD4yMYQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@oxfmt/binding-linux-arm-gnueabihf@0.73.0':
resolution: {integrity: sha512-7qnZ4g0ZCO3aZevOOQpZIABYwwXJW1lLDo2elviGdPQ0i11255xKEMFsi97fC1/nauQFseCJfELUy/k2JoOP+g==}
'@oxfmt/binding-linux-arm-gnueabihf@0.41.0':
resolution: {integrity: sha512-ptazDjdUyhket01IjPTT6ULS1KFuBfTUU97osTP96X5y/0oso+AgAaJzuH81oP0+XXyrWIHbRzozSAuQm4p48g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxfmt/binding-linux-arm-musleabihf@0.73.0':
resolution: {integrity: sha512-36eBico2j/WPB84gb4FYd/jjqGCKOwU4M+TWLBUIqlnzTozQueLy0joA5BwsSp2OZFVkOlpCwvA3ndPamdiyLw==}
'@oxfmt/binding-linux-arm-musleabihf@0.41.0':
resolution: {integrity: sha512-UkoL2OKxFD+56bPEBcdGn+4juTW4HRv/T6w1dIDLnvKKWr6DbarB/mtHXlADKlFiJubJz8pRkttOR7qjYR6lTA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxfmt/binding-linux-arm64-gnu@0.73.0':
resolution: {integrity: sha512-VZ3cSgCAT18knKo52DcACmAuIoqG6qVEyeZRFbJd0xmYQ8GyYjuBc6IAh6MZHijT6q7p4/HPI+6ZWsCuhdV6iw==}
'@oxfmt/binding-linux-arm64-gnu@0.41.0':
resolution: {integrity: sha512-gofu0PuumSOHYczD8p62CPY4UF6ee+rSLZJdUXkpwxg6pILiwSDBIouPskjF/5nF3A7QZTz2O9KFNkNxxFN9tA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-arm64-musl@0.73.0':
resolution: {integrity: sha512-8YVzH59XSHcqwXNgc5qK851zCqwpmBgOifARXEPPe5/xTsIbHceYoPZAyqfpYV0CfKmzSaEDBgYHFza4rhx+Zw==}
'@oxfmt/binding-linux-arm64-musl@0.41.0':
resolution: {integrity: sha512-VfVZxL0+6RU86T8F8vKiDBa+iHsr8PAjQmKGBzSCAX70b6x+UOMFl+2dNihmKmUwqkCazCPfYjt6SuAPOeQJ3g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@oxfmt/binding-linux-ppc64-gnu@0.73.0':
resolution: {integrity: sha512-MqRJnmCys0rwOgpWyEidSA7v/bvOqfNDJhPkQoR9mPVYrvSmMaW2Xhdpl28cbTA+brOM1is62GjIvJplVlUVpw==}
'@oxfmt/binding-linux-ppc64-gnu@0.41.0':
resolution: {integrity: sha512-bwzokz2eGvdfJbc0i+zXMJ4BBjQPqg13jyWpEEZDOrBCQ91r8KeY2Mi2kUeuMTZNFXju+jcAbAbpyJxRGla0eg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-riscv64-gnu@0.73.0':
resolution: {integrity: sha512-4t2F3SWJSK/O/kRRFnL0elJzn75fJGGu71gs1HtiWcS80SmJOpkHiwwLnTp9suGdns8VHEPxYS0GTcyVwHKWBA==}
'@oxfmt/binding-linux-riscv64-gnu@0.41.0':
resolution: {integrity: sha512-POLM//PCH9uqDeNDwWL3b3DkMmI3oI2cU6hwc2lnztD1o7dzrQs3R9nq555BZ6wI7t2lyhT9CS+CRaz5X0XqLA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-riscv64-musl@0.73.0':
resolution: {integrity: sha512-D8b4I8I1kLdJQFwdFXNV+cwh3xWSiNKofjdGUk0nDpc0AHOds8T+poGbP9RWQMvgsvMb9OMgp/aV7ahBR37TbQ==}
'@oxfmt/binding-linux-riscv64-musl@0.41.0':
resolution: {integrity: sha512-NNK7PzhFqLUwx/G12Xtm6scGv7UITvyGdAR5Y+TlqsG+essnuRWR4jRNODWRjzLZod0T3SayRbnkSIWMBov33w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@oxfmt/binding-linux-s390x-gnu@0.73.0':
resolution: {integrity: sha512-QrC1S5VL1+N5rvorB15jH7CPvjVHA7GyUI5oVEd8Bd9m5605RDBQYTxDQ920DuylRoZOh2V7/xXpfCtFUrojUQ==}
'@oxfmt/binding-linux-s390x-gnu@0.41.0':
resolution: {integrity: sha512-qVf/zDC5cN9eKe4qI/O/m445er1IRl6swsSl7jHkqmOSVfknwCe5JXitYjZca+V/cNJSU/xPlC5EFMabMMFDpw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-x64-gnu@0.73.0':
resolution: {integrity: sha512-dFcUKQPltCEPa+YlkF3zqufn6nJPZdG73LpnjBvZFFsU3laCMssDXSYB99mVaj43FqdEgjpz5TO6gbYXcczd9g==}
'@oxfmt/binding-linux-x64-gnu@0.41.0':
resolution: {integrity: sha512-ojxYWu7vUb6ysYqVCPHuAPVZHAI40gfZ0PDtZAMwVmh2f0V8ExpPIKoAKr7/8sNbAXJBBpZhs2coypIo2jJX4w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@oxfmt/binding-linux-x64-musl@0.73.0':
resolution: {integrity: sha512-LmQe+nV8e+eUwfPNCxDF+owbsg88toBiR/8rZRgVOeKQP3MaGefXZRvBoc1UG37iWEQ/9JlCXG9Mc4nf4N3agw==}
'@oxfmt/binding-linux-x64-musl@0.41.0':
resolution: {integrity: sha512-O2exZLBxoCMIv2vlvcbkdedazJPTdG0VSup+0QUCfYQtx751zCZNboX2ZUOiQ/gDTdhtXvSiot0h6GEGkOyalA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@oxfmt/binding-openharmony-arm64@0.73.0':
resolution: {integrity: sha512-8weOr1OKknE0G2DbR6ejJUT9AOsoBU6cXlsetmbihHv1K+bK7qP61T6lJxY0k/aAO7GyOJiRGNlL+04r4eH8Xg==}
'@oxfmt/binding-openharmony-arm64@0.41.0':
resolution: {integrity: sha512-N+31/VoL+z+NNBt8viy3I4NaIdPbiYeOnB884LKqvXldaE2dRztdPv3q5ipfZYv0RwFp7JfqS4I27K/DSHCakg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@oxfmt/binding-win32-arm64-msvc@0.73.0':
resolution: {integrity: sha512-mZV+QxXYgb8E18gzAFItb937VIsE4dqWdStrD3tRRC52UubOYEuU+e7NaIqUsGdB5YsJqNeuck3Ue/af2r9wyA==}
'@oxfmt/binding-win32-arm64-msvc@0.41.0':
resolution: {integrity: sha512-Z7NAtu/RN8kjCQ1y5oDD0nTAeRswh3GJ93qwcW51srmidP7XPBmZbLlwERu1W5veCevQJtPS9xmkpcDTYsGIwQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@oxfmt/binding-win32-ia32-msvc@0.73.0':
resolution: {integrity: sha512-QJPUsbgUb97ZPPMkFUq6VQq0fLhC4Np19KL9aB/qKVwXnpKE6MIiILXqzhKnQ/UbnEDjKJ7Xv1d6zH4bYPCUdQ==}
'@oxfmt/binding-win32-ia32-msvc@0.41.0':
resolution: {integrity: sha512-uNxxP3l4bJ6VyzIeRqCmBU2Q0SkCFgIhvx9/9dJ9V8t/v+jP1IBsuaLwCXGR8JPHtkj4tFp+RHtUmU2ZYAUpMA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ia32]
os: [win32]
'@oxfmt/binding-win32-x64-msvc@0.73.0':
resolution: {integrity: sha512-cGcze2fu+ykIaFtkEvZlkZ3HvnCLk+WISthtq99zWTWn0x13t5L9TxvGdLZMUMvtfYR+ICkiCwKnguVubdcw0w==}
'@oxfmt/binding-win32-x64-msvc@0.41.0':
resolution: {integrity: sha512-49ZSpbZ1noozyPapE8SUOSm3IN0Ze4b5nkO+4+7fq6oEYQQJFhE0saj5k/Gg4oewVPdjn0L3ZFeWk2Vehjcw7A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
'@oxlint-tsgolint/darwin-arm64@7.0.2004':
resolution: {integrity: sha512-uJk3ttju7Lz+Nv8WG4CsLyewoL1qf/Ny8S8OksJ7Bm/F14Tc9gMfW6arM1PCc57IzH/X/I79YsCWTgxX1FKibQ==}
'@oxlint-tsgolint/darwin-arm64@0.20.0':
resolution: {integrity: sha512-KKQcIHZHMxqpHUA1VXIbOG6chNCFkUWbQy6M+AFVtPKkA/3xAeJkJ3njoV66bfzwPHRcWQO+kcj5XqtbkjakoA==}
cpu: [arm64]
os: [darwin]
'@oxlint-tsgolint/darwin-x64@7.0.2004':
resolution: {integrity: sha512-0BFfHTzDxNDFPcu0UZAXT6CyCJHAXM0dZveyDb4KEHa2qF/DSnOKOrmvK/wFuFol9kvijbGM9JfuOsor+zWXRw==}
'@oxlint-tsgolint/darwin-x64@0.20.0':
resolution: {integrity: sha512-7HeVMuclGfG+NLZi2ybY0T4fMI7/XxO/208rJk+zEIloKkVnlh11Wd241JMGwgNFXn+MLJbOqOfojDb2Dt4L1g==}
cpu: [x64]
os: [darwin]
'@oxlint-tsgolint/linux-arm64@7.0.2004':
resolution: {integrity: sha512-TAehQc+qdRXyDN3nl/r/3/oPrBVrbtrDeGMkFyG6mf+XphpoJ2lAMVFLclyvrVZCw02RbKROjyw8h72XwQQHcw==}
'@oxlint-tsgolint/linux-arm64@0.20.0':
resolution: {integrity: sha512-zxhUwz+WSxE6oWlZLK2z2ps9yC6ebmgoYmjAl0Oa48+GqkZ56NVgo+wb8DURNv6xrggzHStQxqQxe3mK51HZag==}
cpu: [arm64]
os: [linux]
'@oxlint-tsgolint/linux-x64@7.0.2004':
resolution: {integrity: sha512-LPunZvm6ZbWPfHMAyfZf9ci3HHvNEzLejO8zdqO3GoVGoSEHqqufHUD7+OgeatVSaJP7uXDJ2HaNOHIoH7go4Q==}
'@oxlint-tsgolint/linux-x64@0.20.0':
resolution: {integrity: sha512-/1l6FnahC9im8PK+Ekkx/V3yetO/PzZnJegE2FXcv/iXEhbeVxP/ouiTYcUQu9shT1FWJCSNti1VJHH+21Y1dg==}
cpu: [x64]
os: [linux]
'@oxlint-tsgolint/win32-arm64@7.0.2004':
resolution: {integrity: sha512-FVWplzDImWhiuawnIZVETaQecv4GWom6Jv4Fx2xj7hhXXDZ5okEgiw1gTCImHTIQsi2ycC5oSxVwrn69bMh7iw==}
'@oxlint-tsgolint/win32-arm64@0.20.0':
resolution: {integrity: sha512-oPZ5Yz8sVdo7P/5q+i3IKeix31eFZ55JAPa1+RGPoe9PoaYVsdMvR6Jvib6YtrqoJnFPlg3fjEjlEPL8VBKYJA==}
cpu: [arm64]
os: [win32]
'@oxlint-tsgolint/win32-x64@7.0.2004':
resolution: {integrity: sha512-7PsxuUx11Ry9DYTWcljTzRbmZY9B6O9fFFfZV+aodQEMy6pfRT3fhoQRv9PtGN/89z1pPz3nFKrsFm6WqNtX7w==}
'@oxlint-tsgolint/win32-x64@0.20.0':
resolution: {integrity: sha512-4stx8RHj3SP9vQyRF/yZbz5igtPvYMEUR8CUoha4BVNZihi39DpCR8qkU7lpjB5Ga1DRMo2pHaA4bdTOMaY4mw==}
cpu: [x64]
os: [win32]
'@oxlint/binding-android-arm-eabi@1.88.0':
resolution: {integrity: sha512-k6Fgkf86ubfeH4GvqYsRolfuVAp0pfYVZvifSlXNHPdMaWUOfxUrmLEeDD7hF6U2oJuhsVxhSWq86/xCJ+9MmA==}
'@oxlint/binding-android-arm-eabi@1.61.0':
resolution: {integrity: sha512-6eZBPgiigK5txqoVgRqxbaxiom4lM8AP8CyKPPvpzKnQ3iFRFOIDc+0AapF+qsUSwjOzr5SGk4SxQDpQhkSJMQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [android]
'@oxlint/binding-android-arm64@1.88.0':
resolution: {integrity: sha512-AsIyhl9o1ejwtac7NMbhKpMdSml6NWR0ljKjZERxC8OHYDAW8o/Om9n1QHVLi4VCEUo42Zte2/Op9kyoGpJZMg==}
'@oxlint/binding-android-arm64@1.61.0':
resolution: {integrity: sha512-CkwLR69MUnyv5wjzebvbbtTSUwqLxM35CXE79bHqDIK+NtKmPEUpStTcLQRZMCo4MP0qRT6TXIQVpK0ZVScnMA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
'@oxlint/binding-darwin-arm64@1.88.0':
resolution: {integrity: sha512-qgBjB7eEKcCB4RqjXGuoSZq74g0wD09fWFJ+HWcCJcKaga8TeUHtb+BY0SsxdleSLBgx4RZ7qmgo0EzqEq7JoQ==}
'@oxlint/binding-darwin-arm64@1.61.0':
resolution: {integrity: sha512-8JbefTkbmvqkqWjmQrHke+MdpgT2UghhD/ktM4FOQSpGeCgbMToJEKdl9zwhr/YWTl92i4QI1KiTwVExpcUN8A==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
'@oxlint/binding-darwin-x64@1.88.0':
resolution: {integrity: sha512-sCz3X5Mw/xdzEzn4fsCt1Iq8NKJnGNfhR+b9B5k+4DysYAHsmIhYoocnBPiQ9kvY3+pUun2A0Z8Vtun/Nv6YoQ==}
'@oxlint/binding-darwin-x64@1.61.0':
resolution: {integrity: sha512-uWpoxDT47hTnDLcdEh5jVbso8rlTTu5o0zuqa9J8E0JAKmIWn7kGFEIB03Pycn2hd2vKxybPGLhjURy/9We5FQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
'@oxlint/binding-freebsd-x64@1.88.0':
resolution: {integrity: sha512-xTOdYOIqCufgIj0knvxu86FBfovP6QBiD7ngNva01gb8xPQCD5gXkE5APGczH35zStim1O3zqvFbLQmY85xXRg==}
'@oxlint/binding-freebsd-x64@1.61.0':
resolution: {integrity: sha512-K/o4hEyW7flfMel0iBVznmMBt7VIMHGdjADocHKpK1DUF9erpWnJ+BSSWd2W0c8K3mPtpph+CuHzRU6CI3l9jQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
'@oxlint/binding-linux-arm-gnueabihf@1.88.0':
resolution: {integrity: sha512-BLadtw88NdYJBrAtC1dYzrPfSP2d5zgx6iuZycdD0YmZBJ2Nqbit9Z4PSaIb6gxK25dweArGMPbOmq/0ugwUPg==}
'@oxlint/binding-linux-arm-gnueabihf@1.61.0':
resolution: {integrity: sha512-P6040ZkcyweJ0Po9yEFqJCdvZnf3VNCGs1SIHgXDf8AAQNC6ID/heXQs9iSgo2FH7gKaKq32VWc59XZwL34C5Q==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxlint/binding-linux-arm-musleabihf@1.88.0':
resolution: {integrity: sha512-wILSczl/DaZsCcf7j7tvNbssp8hxEHIJxrv4j7+JjI3TAL1U/JTWbeUtoJJC/vo8+2hkTmHLYoKJjmiNbijdXw==}
'@oxlint/binding-linux-arm-musleabihf@1.61.0':
resolution: {integrity: sha512-bwxrGCzTZkuB+THv2TQ1aTkVEfv5oz8sl+0XZZCpoYzErJD8OhPQOTA0ENPd1zJz8QsVdSzSrS2umKtPq4/JXg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
'@oxlint/binding-linux-arm64-gnu@1.88.0':
resolution: {integrity: sha512-jutT2Hy8JCuZuMwIFHo2HtyxfOfBJHyQxlBHBK1SL9W2f8n/WhjAP0FnDMz9d/mjhv9+QA0mx5AdQ9fDjsrFFg==}
'@oxlint/binding-linux-arm64-gnu@1.61.0':
resolution: {integrity: sha512-vkhb9/wKguMkLlrm3FoJW/Xmdv31GgYAE+x8lxxQ+7HeOxXUySI0q36a3NTVIuQUdLzxCI1zzMGsk1o37FOe3w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@oxlint/binding-linux-arm64-musl@1.88.0':
resolution: {integrity: sha512-8N8iGV9hh4Lkeuq7QsEkjoXNRRflqR1G2qyoGYXcA0k5qllrdqmfylKEXyHIVERxqNDyMO4StqDQ0uLxXcBQAg==}
'@oxlint/binding-linux-arm64-musl@1.61.0':
resolution: {integrity: sha512-bl1dQh8LnVqsj6oOQAcxwbuOmNJkwc4p6o//HTBZhNTzJy21TLDwAviMqUFNUxDHkPGpmdKTSN4tWTjLryP8xg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [linux]
libc: [musl]
'@oxlint/binding-linux-ppc64-gnu@1.88.0':
resolution: {integrity: sha512-5ydcQt3znNQ/rGEWYRvpS2cK9+T18P2VYgnyJ+eloEAwi9YUmsXy5VGrRqNWIK6qzWwHGnEE3ojVqqQNo+f0hA==}
'@oxlint/binding-linux-ppc64-gnu@1.61.0':
resolution: {integrity: sha512-QoOX6KB2IiEpyOj/HKqaxi+NQHPnOgNgnr22n9N4ANJCzXkUlj1UmeAbFb4PpqdlHIzvGDM5xZ0OKtcLq9RhiQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@oxlint/binding-linux-riscv64-gnu@1.88.0':
resolution: {integrity: sha512-iGx0uvFT54b/5DPJdEBCxYIrVB3v0uTy+JhRh3CyEp8/22BXDkG8rffkFwREdLsdj9mOrPbJYVOZw8ipcBuzjw==}
'@oxlint/binding-linux-riscv64-gnu@1.61.0':
resolution: {integrity: sha512-1TGcTerjY6p152wCof3oKElccq3xHljS/Mucp04gV/4ATpP6nO7YNnp7opEg6SHkv2a57/b4b8Ndm9znJ1/qAw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@oxlint/binding-linux-riscv64-musl@1.88.0':
resolution: {integrity: sha512-Wt47mKMWelVjRjuR7BCFxXkB0m79K1sTEbqMHRWciKUgo5iv7sWsF4RXSOyFYHD9zerNrkRZblnN273rhwOA1Q==}
'@oxlint/binding-linux-riscv64-musl@1.61.0':
resolution: {integrity: sha512-65wXEmZIrX2ADwC8i/qFL4EWLSbeuBpAm3suuX1vu4IQkKd+wLT/HU/BOl84kp91u2SxPkPDyQgu4yrqp8vwVA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@oxlint/binding-linux-s390x-gnu@1.88.0':
resolution: {integrity: sha512-g3L12KCS4+1gtUt3RbJ4F+Yxx4LNmmZLEPfhd8rAHEJjJk2lAgNfnjGoP/phJyhG5WS6VbNYbJtadJelNfvTMA==}
'@oxlint/binding-linux-s390x-gnu@1.61.0':
resolution: {integrity: sha512-TVvhgMvor7Qa6COeXxCJ7ENOM+lcAOGsQ0iUdPSCv2hxb9qSHLQ4XF1h50S6RE1gBOJ0WV3rNukg4JJJP1LWRA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@oxlint/binding-linux-x64-gnu@1.88.0':
resolution: {integrity: sha512-og/XHVDOD9ZJgRiZkT9DgzQd4sr+JZW7e4l17Q/jVMZiIbeEd4uIu9iAoUbTF1gIvVZoRc4QDOxyVUvQGp4WHg==}
'@oxlint/binding-linux-x64-gnu@1.61.0':
resolution: {integrity: sha512-SjpS5uYuFoDnDdZPwZE59ndF95AsY47R5MliuneTWR1pDm2CxGJaYXbKULI71t5TVfLQUWmrHEGRL9xvuq6dnA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [glibc]
'@oxlint/binding-linux-x64-musl@1.88.0':
resolution: {integrity: sha512-EmhBsp+xuKb6YbZNEMLBo80Xw71AZOIm18do8ni/GLX/Lw1XzNhVYpbxO1KasYtoAvrGtCOdCPULRlIE0bPbTQ==}
'@oxlint/binding-linux-x64-musl@1.61.0':
resolution: {integrity: sha512-gGfAeGD4sNJGILZbc/yKcIimO9wQnPMoYp9swAaKeEtwsSQAbU+rsdQze5SBtIP6j0QDzeYd4XSSUCRCF+LIeQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [linux]
libc: [musl]
'@oxlint/binding-openharmony-arm64@1.88.0':
resolution: {integrity: sha512-DBUcx/KwYdg1DAz+G01P/GFv512J04EsZadbHptx2FTpWT/MWRg21ZToNHt9pnsfQRBQ3et/g+vqzbvrdAVbuA==}
'@oxlint/binding-openharmony-arm64@1.61.0':
resolution: {integrity: sha512-OlVT0LrG/ct33EVtWRyR+B/othwmDWeRxfi13wUdPeb3lAT5TgTcFDcfLfarZtzB4W1nWF/zICMgYdkggX2WmQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
'@oxlint/binding-win32-arm64-msvc@1.88.0':
resolution: {integrity: sha512-xeVd0n4XG5HvynxfYvXi6uB+JvZbVZataowPS8cYpMbYg9mwE4sSyElFQd4LVJFifq8bRLDSR18XgEildmcXAg==}
'@oxlint/binding-win32-arm64-msvc@1.61.0':
resolution: {integrity: sha512-vI//NZPJk6DToiovPtaiwD4iQ7kO1r5ReWQD0sOOyKRtP3E2f6jxin4uvwi3OvDzHA2EFfd7DcZl5dtkQh7g1w==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
'@oxlint/binding-win32-ia32-msvc@1.88.0':
resolution: {integrity: sha512-MA6iOw//amleaz2mVMsZrA7NHlEexjTrhIxSMFCXQi6IUuQO+3Od00GZhr2iCYw6RFzMW36jkKK/WHBXMsoQAw==}
'@oxlint/binding-win32-ia32-msvc@1.61.0':
resolution: {integrity: sha512-0ySj4/4zd2XjePs3XAQq7IigIstN4LPQZgCyigX5/ERMLjdWAJfnxcTsrtxZxuij8guJW8foXuHmhGxW0H4dDA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [ia32]
os: [win32]
'@oxlint/binding-win32-x64-msvc@1.88.0':
resolution: {integrity: sha512-3Sz6rVWe8Dy+ufsXurFN1GX2dX43F/lQMSLelK9gFjiba7nHvLlqlhR5cHlWVnCpSqUY1hN9pyCX9XToe6ve6g==}
'@oxlint/binding-win32-x64-msvc@1.61.0':
resolution: {integrity: sha512-0xgSiyeqDLDZxXoe9CVJrOx3TUVsfyoOY7cNi03JbItNcC9WCZqrSNdrAbHONxhSPaVh/lzfnDcON1RqSUMhHw==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
@@ -562,38 +546,24 @@ packages:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
oxfmt@0.73.0:
resolution: {integrity: sha512-Ke4xbpuzqIBP4bkd48q815RhqWNJqOBzxVA9199M4qcF0y0LtpUv7UTg1dJ5ea6jw0RBUDZvX3qOUMNmmxfxbw==}
oxfmt@0.41.0:
resolution: {integrity: sha512-sKLdJZdQ3bw6x9qKiT7+eID4MNEXlDHf5ZacfIircrq6Qwjk0L6t2/JQlZZrVHTXJawK3KaMuBoJnEJPcqCEdg==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
oxlint-tsgolint@0.20.0:
resolution: {integrity: sha512-/Uc9TQyN1l8w9QNvXtVHYtz+SzDJHKpb5X0UnHodl0BVzijUPk0LPlDOHAvogd1UI+iy9ZSF6gQxEqfzUxCULQ==}
hasBin: true
oxlint@1.61.0:
resolution: {integrity: sha512-ZC0ALuhDZ6ivOFG+sy0D0pEDN49EvsId98zVlmYdkcXHsEM14m/qTNUEsUpiFiCVbpIxYtVBmmLE87nsbUHohQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
'@astrojs/compiler-rs': ^0.4.0 || ^0.5.0
svelte: ^5.0.0
vite-plus: '*'
peerDependenciesMeta:
'@astrojs/compiler-rs':
optional: true
svelte:
optional: true
vite-plus:
optional: true
oxlint-tsgolint@7.0.2004:
resolution: {integrity: sha512-vQ9WDF3fiZJvRdSDosNOflerOCOpwol6vWzVDxW76RcU19cjTh7engvkHLvmv+tzedR8fAiJUVUGr6IVZdkzXQ==}
hasBin: true
oxlint@1.88.0:
resolution: {integrity: sha512-uIcFgw8BmqvFRGzH5+r7d2zJMEexwNSrEmM6WQNnGh3VkO0XYTEFoyxyNE6tjKMUib9Cue4XJA2DoWruO5D6aw==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
oxlint-tsgolint: '>=7.0.2003'
vite-plus: '*'
oxlint-tsgolint: '>=0.18.0'
peerDependenciesMeta:
oxlint-tsgolint:
optional: true
vite-plus:
optional: true
p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
@@ -637,8 +607,8 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
tinypool@2.2.0:
resolution: {integrity: sha512-jBrmx4lYmaC9k/mgPbylxs7kBUxHtD8256up+HjLaDFfXScKJQyil+SWXSvhAtT7XHo+yTVlpB81PGmHP8oLSQ==}
tinypool@2.1.0:
resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==}
engines: {node: ^20.0.0 || >=22.0.0}
type-check@0.4.0:
@@ -717,136 +687,136 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
'@oxfmt/binding-android-arm-eabi@0.73.0':
'@oxfmt/binding-android-arm-eabi@0.41.0':
optional: true
'@oxfmt/binding-android-arm64@0.73.0':
'@oxfmt/binding-android-arm64@0.41.0':
optional: true
'@oxfmt/binding-darwin-arm64@0.73.0':
'@oxfmt/binding-darwin-arm64@0.41.0':
optional: true
'@oxfmt/binding-darwin-x64@0.73.0':
'@oxfmt/binding-darwin-x64@0.41.0':
optional: true
'@oxfmt/binding-freebsd-x64@0.73.0':
'@oxfmt/binding-freebsd-x64@0.41.0':
optional: true
'@oxfmt/binding-linux-arm-gnueabihf@0.73.0':
'@oxfmt/binding-linux-arm-gnueabihf@0.41.0':
optional: true
'@oxfmt/binding-linux-arm-musleabihf@0.73.0':
'@oxfmt/binding-linux-arm-musleabihf@0.41.0':
optional: true
'@oxfmt/binding-linux-arm64-gnu@0.73.0':
'@oxfmt/binding-linux-arm64-gnu@0.41.0':
optional: true
'@oxfmt/binding-linux-arm64-musl@0.73.0':
'@oxfmt/binding-linux-arm64-musl@0.41.0':
optional: true
'@oxfmt/binding-linux-ppc64-gnu@0.73.0':
'@oxfmt/binding-linux-ppc64-gnu@0.41.0':
optional: true
'@oxfmt/binding-linux-riscv64-gnu@0.73.0':
'@oxfmt/binding-linux-riscv64-gnu@0.41.0':
optional: true
'@oxfmt/binding-linux-riscv64-musl@0.73.0':
'@oxfmt/binding-linux-riscv64-musl@0.41.0':
optional: true
'@oxfmt/binding-linux-s390x-gnu@0.73.0':
'@oxfmt/binding-linux-s390x-gnu@0.41.0':
optional: true
'@oxfmt/binding-linux-x64-gnu@0.73.0':
'@oxfmt/binding-linux-x64-gnu@0.41.0':
optional: true
'@oxfmt/binding-linux-x64-musl@0.73.0':
'@oxfmt/binding-linux-x64-musl@0.41.0':
optional: true
'@oxfmt/binding-openharmony-arm64@0.73.0':
'@oxfmt/binding-openharmony-arm64@0.41.0':
optional: true
'@oxfmt/binding-win32-arm64-msvc@0.73.0':
'@oxfmt/binding-win32-arm64-msvc@0.41.0':
optional: true
'@oxfmt/binding-win32-ia32-msvc@0.73.0':
'@oxfmt/binding-win32-ia32-msvc@0.41.0':
optional: true
'@oxfmt/binding-win32-x64-msvc@0.73.0':
'@oxfmt/binding-win32-x64-msvc@0.41.0':
optional: true
'@oxlint-tsgolint/darwin-arm64@7.0.2004':
'@oxlint-tsgolint/darwin-arm64@0.20.0':
optional: true
'@oxlint-tsgolint/darwin-x64@7.0.2004':
'@oxlint-tsgolint/darwin-x64@0.20.0':
optional: true
'@oxlint-tsgolint/linux-arm64@7.0.2004':
'@oxlint-tsgolint/linux-arm64@0.20.0':
optional: true
'@oxlint-tsgolint/linux-x64@7.0.2004':
'@oxlint-tsgolint/linux-x64@0.20.0':
optional: true
'@oxlint-tsgolint/win32-arm64@7.0.2004':
'@oxlint-tsgolint/win32-arm64@0.20.0':
optional: true
'@oxlint-tsgolint/win32-x64@7.0.2004':
'@oxlint-tsgolint/win32-x64@0.20.0':
optional: true
'@oxlint/binding-android-arm-eabi@1.88.0':
'@oxlint/binding-android-arm-eabi@1.61.0':
optional: true
'@oxlint/binding-android-arm64@1.88.0':
'@oxlint/binding-android-arm64@1.61.0':
optional: true
'@oxlint/binding-darwin-arm64@1.88.0':
'@oxlint/binding-darwin-arm64@1.61.0':
optional: true
'@oxlint/binding-darwin-x64@1.88.0':
'@oxlint/binding-darwin-x64@1.61.0':
optional: true
'@oxlint/binding-freebsd-x64@1.88.0':
'@oxlint/binding-freebsd-x64@1.61.0':
optional: true
'@oxlint/binding-linux-arm-gnueabihf@1.88.0':
'@oxlint/binding-linux-arm-gnueabihf@1.61.0':
optional: true
'@oxlint/binding-linux-arm-musleabihf@1.88.0':
'@oxlint/binding-linux-arm-musleabihf@1.61.0':
optional: true
'@oxlint/binding-linux-arm64-gnu@1.88.0':
'@oxlint/binding-linux-arm64-gnu@1.61.0':
optional: true
'@oxlint/binding-linux-arm64-musl@1.88.0':
'@oxlint/binding-linux-arm64-musl@1.61.0':
optional: true
'@oxlint/binding-linux-ppc64-gnu@1.88.0':
'@oxlint/binding-linux-ppc64-gnu@1.61.0':
optional: true
'@oxlint/binding-linux-riscv64-gnu@1.88.0':
'@oxlint/binding-linux-riscv64-gnu@1.61.0':
optional: true
'@oxlint/binding-linux-riscv64-musl@1.88.0':
'@oxlint/binding-linux-riscv64-musl@1.61.0':
optional: true
'@oxlint/binding-linux-s390x-gnu@1.88.0':
'@oxlint/binding-linux-s390x-gnu@1.61.0':
optional: true
'@oxlint/binding-linux-x64-gnu@1.88.0':
'@oxlint/binding-linux-x64-gnu@1.61.0':
optional: true
'@oxlint/binding-linux-x64-musl@1.88.0':
'@oxlint/binding-linux-x64-musl@1.61.0':
optional: true
'@oxlint/binding-openharmony-arm64@1.88.0':
'@oxlint/binding-openharmony-arm64@1.61.0':
optional: true
'@oxlint/binding-win32-arm64-msvc@1.88.0':
'@oxlint/binding-win32-arm64-msvc@1.61.0':
optional: true
'@oxlint/binding-win32-ia32-msvc@1.88.0':
'@oxlint/binding-win32-ia32-msvc@1.61.0':
optional: true
'@oxlint/binding-win32-x64-msvc@1.88.0':
'@oxlint/binding-win32-x64-msvc@1.61.0':
optional: true
'@playwright/test@1.57.0':
@@ -1046,61 +1016,61 @@ snapshots:
type-check: 0.4.0
word-wrap: 1.2.5
oxfmt@0.73.0:
oxfmt@0.41.0:
dependencies:
tinypool: 2.2.0
tinypool: 2.1.0
optionalDependencies:
'@oxfmt/binding-android-arm-eabi': 0.73.0
'@oxfmt/binding-android-arm64': 0.73.0
'@oxfmt/binding-darwin-arm64': 0.73.0
'@oxfmt/binding-darwin-x64': 0.73.0
'@oxfmt/binding-freebsd-x64': 0.73.0
'@oxfmt/binding-linux-arm-gnueabihf': 0.73.0
'@oxfmt/binding-linux-arm-musleabihf': 0.73.0
'@oxfmt/binding-linux-arm64-gnu': 0.73.0
'@oxfmt/binding-linux-arm64-musl': 0.73.0
'@oxfmt/binding-linux-ppc64-gnu': 0.73.0
'@oxfmt/binding-linux-riscv64-gnu': 0.73.0
'@oxfmt/binding-linux-riscv64-musl': 0.73.0
'@oxfmt/binding-linux-s390x-gnu': 0.73.0
'@oxfmt/binding-linux-x64-gnu': 0.73.0
'@oxfmt/binding-linux-x64-musl': 0.73.0
'@oxfmt/binding-openharmony-arm64': 0.73.0
'@oxfmt/binding-win32-arm64-msvc': 0.73.0
'@oxfmt/binding-win32-ia32-msvc': 0.73.0
'@oxfmt/binding-win32-x64-msvc': 0.73.0
'@oxfmt/binding-android-arm-eabi': 0.41.0
'@oxfmt/binding-android-arm64': 0.41.0
'@oxfmt/binding-darwin-arm64': 0.41.0
'@oxfmt/binding-darwin-x64': 0.41.0
'@oxfmt/binding-freebsd-x64': 0.41.0
'@oxfmt/binding-linux-arm-gnueabihf': 0.41.0
'@oxfmt/binding-linux-arm-musleabihf': 0.41.0
'@oxfmt/binding-linux-arm64-gnu': 0.41.0
'@oxfmt/binding-linux-arm64-musl': 0.41.0
'@oxfmt/binding-linux-ppc64-gnu': 0.41.0
'@oxfmt/binding-linux-riscv64-gnu': 0.41.0
'@oxfmt/binding-linux-riscv64-musl': 0.41.0
'@oxfmt/binding-linux-s390x-gnu': 0.41.0
'@oxfmt/binding-linux-x64-gnu': 0.41.0
'@oxfmt/binding-linux-x64-musl': 0.41.0
'@oxfmt/binding-openharmony-arm64': 0.41.0
'@oxfmt/binding-win32-arm64-msvc': 0.41.0
'@oxfmt/binding-win32-ia32-msvc': 0.41.0
'@oxfmt/binding-win32-x64-msvc': 0.41.0
oxlint-tsgolint@7.0.2004:
oxlint-tsgolint@0.20.0:
optionalDependencies:
'@oxlint-tsgolint/darwin-arm64': 7.0.2004
'@oxlint-tsgolint/darwin-x64': 7.0.2004
'@oxlint-tsgolint/linux-arm64': 7.0.2004
'@oxlint-tsgolint/linux-x64': 7.0.2004
'@oxlint-tsgolint/win32-arm64': 7.0.2004
'@oxlint-tsgolint/win32-x64': 7.0.2004
'@oxlint-tsgolint/darwin-arm64': 0.20.0
'@oxlint-tsgolint/darwin-x64': 0.20.0
'@oxlint-tsgolint/linux-arm64': 0.20.0
'@oxlint-tsgolint/linux-x64': 0.20.0
'@oxlint-tsgolint/win32-arm64': 0.20.0
'@oxlint-tsgolint/win32-x64': 0.20.0
oxlint@1.88.0(oxlint-tsgolint@7.0.2004):
oxlint@1.61.0(oxlint-tsgolint@0.20.0):
optionalDependencies:
'@oxlint/binding-android-arm-eabi': 1.88.0
'@oxlint/binding-android-arm64': 1.88.0
'@oxlint/binding-darwin-arm64': 1.88.0
'@oxlint/binding-darwin-x64': 1.88.0
'@oxlint/binding-freebsd-x64': 1.88.0
'@oxlint/binding-linux-arm-gnueabihf': 1.88.0
'@oxlint/binding-linux-arm-musleabihf': 1.88.0
'@oxlint/binding-linux-arm64-gnu': 1.88.0
'@oxlint/binding-linux-arm64-musl': 1.88.0
'@oxlint/binding-linux-ppc64-gnu': 1.88.0
'@oxlint/binding-linux-riscv64-gnu': 1.88.0
'@oxlint/binding-linux-riscv64-musl': 1.88.0
'@oxlint/binding-linux-s390x-gnu': 1.88.0
'@oxlint/binding-linux-x64-gnu': 1.88.0
'@oxlint/binding-linux-x64-musl': 1.88.0
'@oxlint/binding-openharmony-arm64': 1.88.0
'@oxlint/binding-win32-arm64-msvc': 1.88.0
'@oxlint/binding-win32-ia32-msvc': 1.88.0
'@oxlint/binding-win32-x64-msvc': 1.88.0
oxlint-tsgolint: 7.0.2004
'@oxlint/binding-android-arm-eabi': 1.61.0
'@oxlint/binding-android-arm64': 1.61.0
'@oxlint/binding-darwin-arm64': 1.61.0
'@oxlint/binding-darwin-x64': 1.61.0
'@oxlint/binding-freebsd-x64': 1.61.0
'@oxlint/binding-linux-arm-gnueabihf': 1.61.0
'@oxlint/binding-linux-arm-musleabihf': 1.61.0
'@oxlint/binding-linux-arm64-gnu': 1.61.0
'@oxlint/binding-linux-arm64-musl': 1.61.0
'@oxlint/binding-linux-ppc64-gnu': 1.61.0
'@oxlint/binding-linux-riscv64-gnu': 1.61.0
'@oxlint/binding-linux-riscv64-musl': 1.61.0
'@oxlint/binding-linux-s390x-gnu': 1.61.0
'@oxlint/binding-linux-x64-gnu': 1.61.0
'@oxlint/binding-linux-x64-musl': 1.61.0
'@oxlint/binding-openharmony-arm64': 1.61.0
'@oxlint/binding-win32-arm64-msvc': 1.61.0
'@oxlint/binding-win32-ia32-msvc': 1.61.0
'@oxlint/binding-win32-x64-msvc': 1.61.0
oxlint-tsgolint: 0.20.0
p-limit@3.1.0:
dependencies:
@@ -1132,7 +1102,7 @@ snapshots:
shebang-regex@3.0.0: {}
tinypool@2.2.0: {}
tinypool@2.1.0: {}
type-check@0.4.0:
dependencies: