Update dependency prettier to v3.2.4 (#81047)

* Update dependency prettier to v3.2.4

* update sdk + run prettier

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Ashley Harrison <ashley.harrison@grafana.com>
This commit is contained in:
renovate[bot] 2024-01-23 11:41:24 +00:00 committed by GitHub
parent 3d033839d7
commit 86cb412b1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 172 additions and 211 deletions

View File

@ -1,6 +1,6 @@
{
"name": "prettier",
"version": "3.0.0-sdk",
"version": "3.2.4-sdk",
"main": "./index.cjs",
"type": "commonjs",
"bin": "./bin/prettier.cjs"

View File

@ -89,62 +89,26 @@ const addAzureMonitorVariable = (
.type(`${type.replace('Azure', '').trim()}{enter}`);
switch (type) {
case AzureQueryType.ResourceGroupsQuery:
e2eSelectors.variableEditor.subscription
.input()
.find('input')
.type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.subscription.input().find('input').type(`${options?.subscription}{enter}`);
break;
case AzureQueryType.LocationsQuery:
e2eSelectors.variableEditor.subscription
.input()
.find('input')
.type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.subscription.input().find('input').type(`${options?.subscription}{enter}`);
break;
case AzureQueryType.NamespacesQuery:
e2eSelectors.variableEditor.subscription
.input()
.find('input')
.type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.resourceGroup
.input()
.find('input')
.type(`${options?.resourceGroup}{enter}`);
e2eSelectors.variableEditor.subscription.input().find('input').type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.resourceGroup.input().find('input').type(`${options?.resourceGroup}{enter}`);
break;
case AzureQueryType.ResourceNamesQuery:
e2eSelectors.variableEditor.subscription
.input()
.find('input')
.type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.resourceGroup
.input()
.find('input')
.type(`${options?.resourceGroup}{enter}`);
e2eSelectors.variableEditor.namespace
.input()
.find('input')
.type(`${options?.namespace}{enter}`);
e2eSelectors.variableEditor.region
.input()
.find('input')
.type(`${options?.region}{enter}`);
e2eSelectors.variableEditor.subscription.input().find('input').type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.resourceGroup.input().find('input').type(`${options?.resourceGroup}{enter}`);
e2eSelectors.variableEditor.namespace.input().find('input').type(`${options?.namespace}{enter}`);
e2eSelectors.variableEditor.region.input().find('input').type(`${options?.region}{enter}`);
break;
case AzureQueryType.MetricNamesQuery:
e2eSelectors.variableEditor.subscription
.input()
.find('input')
.type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.resourceGroup
.input()
.find('input')
.type(`${options?.resourceGroup}{enter}`);
e2eSelectors.variableEditor.namespace
.input()
.find('input')
.type(`${options?.namespace}{enter}`);
e2eSelectors.variableEditor.resource
.input()
.find('input')
.type(`${options?.resource}{enter}`);
e2eSelectors.variableEditor.subscription.input().find('input').type(`${options?.subscription}{enter}`);
e2eSelectors.variableEditor.resourceGroup.input().find('input').type(`${options?.resourceGroup}{enter}`);
e2eSelectors.variableEditor.namespace.input().find('input').type(`${options?.namespace}{enter}`);
e2eSelectors.variableEditor.resource.input().find('input').type(`${options?.resource}{enter}`);
break;
}
e2e.pages.Dashboard.Settings.Variables.Edit.General.submitButton().click();

View File

@ -12,14 +12,14 @@ export type E2EFunctionWithOnlyOptions = (options?: CypressOptions) => Cypress.C
export type TypeSelectors<S> = S extends StringSelector
? E2EFunctionWithOnlyOptions
: S extends FunctionSelector
? E2EFunction
: S extends CssSelector
? E2EFunction
: S extends UrlSelector
? E2EVisit & Omit<E2EFunctions<S>, 'url'>
: S extends Record<string, string | FunctionSelector | CssSelector | UrlSelector | Selectors>
? E2EFunctions<S>
: S;
? E2EFunction
: S extends CssSelector
? E2EFunction
: S extends UrlSelector
? E2EVisit & Omit<E2EFunctions<S>, 'url'>
: S extends Record<string, string | FunctionSelector | CssSelector | UrlSelector | Selectors>
? E2EFunctions<S>
: S;
export type E2EFunctions<S extends Selectors> = {
[P in keyof S]: TypeSelectors<S[P]>;

View File

@ -192,7 +192,7 @@
"postcss-loader": "7.3.4",
"postcss-reporter": "7.1.0",
"postcss-scss": "4.0.9",
"prettier": "3.0.0",
"prettier": "3.2.4",
"react-refresh": "0.14.0",
"react-select-event": "5.5.1",
"react-simple-compat": "1.2.3",
@ -431,7 +431,7 @@
},
"packageManager": "yarn@4.0.0",
"dependenciesMeta": {
"prettier@3.0.0": {
"prettier@3.2.4": {
"unplugged": true
}
}

View File

@ -46,8 +46,8 @@ export const reduceTransformer: DataTransformerInfo<ReduceTransformerOptions> =
const matcher = options.fields
? getFieldMatcher(options.fields)
: options.includeTimeField && options.mode === ReduceTransformerMode.ReduceFields
? alwaysFieldMatcher
: notTimeFieldMatcher;
? alwaysFieldMatcher
: notTimeFieldMatcher;
// Collapse all matching fields into a single row
if (options.mode === ReduceTransformerMode.ReduceFields) {

View File

@ -14,14 +14,14 @@ export type E2EFunctionWithOnlyOptions = (options?: CypressOptions) => Cypress.C
export type TypeSelectors<S> = S extends StringSelector
? E2EFunctionWithOnlyOptions
: S extends FunctionSelector
? E2EFunction
: S extends CssSelector
? E2EFunction
: S extends UrlSelector
? E2EVisit & Omit<E2EFunctions<S>, 'url'>
: S extends Record<any, any>
? E2EFunctions<S>
: S;
? E2EFunction
: S extends CssSelector
? E2EFunction
: S extends UrlSelector
? E2EVisit & Omit<E2EFunctions<S>, 'url'>
: S extends Record<any, any>
? E2EFunctions<S>
: S;
export type E2EFunctions<S extends Selectors> = {
[P in keyof S]: TypeSelectors<S[P]>;

View File

@ -358,8 +358,8 @@ function useColorFunction(
(colorScheme === ColorSchemeDiff.Default || colorScheme === ColorSchemeDiff.DiffColorBlind)
? getBarColorByDiff(item.value, item.valueRight!, totalTicks, totalTicksRight!, colorScheme)
: colorScheme === ColorScheme.ValueBased
? getBarColorByValue(item.value, totalTicks, rangeMin, rangeMax)
: getBarColorByPackage(label, theme);
? getBarColorByValue(item.value, totalTicks, rangeMin, rangeMax)
: getBarColorByPackage(label, theme);
if (matchedLabels) {
// Means we are searching, we use color for matches and gray the rest

View File

@ -133,8 +133,8 @@ export class Cascader extends PureComponent<CascaderProps, CascaderState> {
const activeLabel = this.props.hideActiveLevelLabel
? ''
: this.props.displayAllSelectedLevels
? selectedOptions.map((option) => option.label).join(this.props.separator || DEFAULT_SEPARATOR)
: selectedOptions[selectedOptions.length - 1].label;
? selectedOptions.map((option) => option.label).join(this.props.separator || DEFAULT_SEPARATOR)
: selectedOptions[selectedOptions.length - 1].label;
this.setState({
rcValue: value,
focusCascade: true,

View File

@ -51,10 +51,10 @@ export class UPlotScaleBuilder extends PlotConfigBuilder<ScaleProps, Scale> {
distr === ScaleDistribution.Symlog
? 4
: distr === ScaleDistribution.Log
? 3
: distr === ScaleDistribution.Ordinal
? 2
: 1,
? 3
: distr === ScaleDistribution.Ordinal
? 2
: 1,
log: distr === ScaleDistribution.Log || distr === ScaleDistribution.Symlog ? this.props.log ?? 2 : undefined,
asinh: distr === ScaleDistribution.Symlog ? this.props.linearThreshold ?? 1 : undefined,
}

View File

@ -123,8 +123,8 @@ export function getStackingGroups(frame: DataFrame) {
drawStyle === GraphDrawStyle.Bars
? custom.barAlignment
: drawStyle === GraphDrawStyle.Line
? custom.lineInterpolation
: null;
? custom.lineInterpolation
: null;
let stackKey = `${stackDir}|${stackingMode}|${stackingGroup}|${buildScaleKey(
config,

View File

@ -259,16 +259,16 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{
return [dataMin, dataMax];
}
: field.type === FieldType.enum
? (u: uPlot, dataMin: number, dataMax: number) => {
// this is the exhaustive enum (stable)
let len = field.config.type!.enum!.text!.length;
? (u: uPlot, dataMin: number, dataMax: number) => {
// this is the exhaustive enum (stable)
let len = field.config.type!.enum!.text!.length;
return [-1, len];
return [-1, len];
// these are only values that are present
// return [dataMin - 1, dataMax + 1]
}
: undefined,
// these are only values that are present
// return [dataMin - 1, dataMax + 1]
}
: undefined,
decimals: field.config.decimals,
},
field

View File

@ -260,16 +260,16 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{
return [dataMin, dataMax];
}
: field.type === FieldType.enum
? (u: uPlot, dataMin: number, dataMax: number) => {
// this is the exhaustive enum (stable)
let len = field.config.type!.enum!.text!.length;
? (u: uPlot, dataMin: number, dataMax: number) => {
// this is the exhaustive enum (stable)
let len = field.config.type!.enum!.text!.length;
return [-1, len];
return [-1, len];
// these are only values that are present
// return [dataMin - 1, dataMax + 1]
}
: undefined,
// these are only values that are present
// return [dataMin - 1, dataMax + 1]
}
: undefined,
decimals: field.config.decimals,
},
field

View File

@ -693,19 +693,19 @@ export function fmtDuration(milliSeconds: number): string {
yr > 0
? yr + 'y ' + (mo > 0 ? mo + 'mo ' : '') + (wk > 0 ? wk + 'w ' : '') + (d > 0 ? d + 'd ' : '')
: mo > 0
? mo + 'mo ' + (wk > 0 ? wk + 'w ' : '') + (d > 0 ? d + 'd ' : '')
: wk > 0
? wk + 'w ' + (d > 0 ? d + 'd ' : '')
: d > 0
? d + 'd ' + (h > 0 ? h + 'h ' : '')
: h > 0
? h + 'h ' + (m > 0 ? m + 'm ' : '')
: m > 0
? m + 'm ' + (s > 0 ? s + 's ' : '')
: s > 0
? s + 's ' + (ms > 0 ? ms + 'ms ' : '')
: ms > 0
? ms + 'ms '
: '0'
? mo + 'mo ' + (wk > 0 ? wk + 'w ' : '') + (d > 0 ? d + 'd ' : '')
: wk > 0
? wk + 'w ' + (d > 0 ? d + 'd ' : '')
: d > 0
? d + 'd ' + (h > 0 ? h + 'h ' : '')
: h > 0
? h + 'h ' + (m > 0 ? m + 'm ' : '')
: m > 0
? m + 'm ' + (s > 0 ? s + 's ' : '')
: s > 0
? s + 's ' + (ms > 0 ? ms + 'ms ' : '')
: ms > 0
? ms + 'ms '
: '0'
).trim();
}

View File

@ -57,8 +57,8 @@ function filterQueriesBySearchFilter(queries: RichHistoryQuery[], searchFilter:
const listOfMatchingQueries = query.queries.filter((query) =>
// Remove fields in which we don't want to be searching
Object.values(omit(query, ['datasource', 'key', 'refId', 'hide', 'queryType'])).some(
(value) => value?.toString().includes(searchFilter)
Object.values(omit(query, ['datasource', 'key', 'refId', 'hide', 'queryType'])).some((value) =>
value?.toString().includes(searchFilter)
)
);

View File

@ -140,8 +140,8 @@ function useAlertsFolderViewParams() {
sortParam === SortOrder.Ascending
? SortOrder.Ascending
: sortParam === SortOrder.Descending
? SortOrder.Descending
: undefined
? SortOrder.Descending
: undefined
);
useDebounce(

View File

@ -55,11 +55,7 @@ export const QueryOptions = ({
</Toggletip>
<div className={styles.staticValues}>
<span>
{dateTime(timeRange?.from)
.locale('en')
.fromNow(true)}
</span>
<span>{dateTime(timeRange?.from).locale('en').fromNow(true)}</span>
{queryOptions.maxDataPoints && <span>, MD = {queryOptions.maxDataPoints}</span>}
{queryOptions.minInterval && <span>, Min. Interval = {queryOptions.minInterval}</span>}
</div>

View File

@ -146,15 +146,14 @@ const useFilteredSilences = (silences: Silence[], expired = false) => {
}
if (queryString) {
const matchers = parseMatchers(queryString);
const matchersMatch = matchers.every(
(matcher) =>
silence.matchers?.some(
({ name, value, isEqual, isRegex }) =>
matcher.name === name &&
matcher.value === value &&
matcher.isEqual === isEqual &&
matcher.isRegex === isRegex
)
const matchersMatch = matchers.every((matcher) =>
silence.matchers?.some(
({ name, value, isEqual, isRegex }) =>
matcher.name === name &&
matcher.value === value &&
matcher.isEqual === isEqual &&
matcher.isRegex === isRegex
)
);
if (!matchersMatch) {
return false;

View File

@ -373,28 +373,28 @@ function rulerRuleToCombinedRule(
filteredInstanceTotals: {},
}
: isRecordingRulerRule(rule)
? {
name: rule.record,
query: rule.expr,
labels: rule.labels || {},
annotations: {},
rulerRule: rule,
namespace,
group,
instanceTotals: {},
filteredInstanceTotals: {},
}
: {
name: rule.grafana_alert.title,
query: '',
labels: rule.labels || {},
annotations: rule.annotations || {},
rulerRule: rule,
namespace,
group,
instanceTotals: {},
filteredInstanceTotals: {},
};
? {
name: rule.record,
query: rule.expr,
labels: rule.labels || {},
annotations: {},
rulerRule: rule,
namespace,
group,
instanceTotals: {},
filteredInstanceTotals: {},
}
: {
name: rule.grafana_alert.title,
query: '',
labels: rule.labels || {},
annotations: rule.annotations || {},
rulerRule: rule,
namespace,
group,
instanceTotals: {},
filteredInstanceTotals: {},
};
}
// find existing rule in group that matches the given prom rule

View File

@ -78,10 +78,10 @@ export const GenAIButton = ({
const buttonItem = error
? AutoGenerateItem.erroredRetryButton
: isFirstHistoryEntry
? AutoGenerateItem.stopGenerationButton
: hasHistory
? AutoGenerateItem.improveButton
: AutoGenerateItem.autoGenerateButton;
? AutoGenerateItem.stopGenerationButton
: hasHistory
? AutoGenerateItem.improveButton
: AutoGenerateItem.autoGenerateButton;
reportInteraction(buttonItem);
};

View File

@ -261,8 +261,8 @@ function useFocusSpanLink(options: {
})
);
const query = useSelector(
(state) => state.explore.panes[options.exploreId]?.queries.find((query) => query.refId === options.refId)
const query = useSelector((state) =>
state.explore.panes[options.exploreId]?.queries.find((query) => query.refId === options.refId)
);
const createFocusSpanLink = (traceId: string, spanId: string) => {
@ -297,22 +297,22 @@ function useFocusSpanLink(options: {
onClickFn: sameTrace
? () => setFocusedSpanId(focusedSpanId === spanId ? undefined : spanId)
: options.splitOpenFn
? () =>
options.splitOpenFn({
datasourceUid: options.datasource?.uid!,
queries: [
{
...query!,
query: traceId,
? () =>
options.splitOpenFn({
datasourceUid: options.datasource?.uid!,
queries: [
{
...query!,
query: traceId,
},
],
panelsState: {
trace: {
spanId,
},
},
],
panelsState: {
trace: {
spanId,
},
},
})
: undefined,
})
: undefined,
replaceVariables: getTemplateSrv().replace.bind(getTemplateSrv()),
});
};

View File

@ -898,8 +898,8 @@ describe('LiveDataStream', () => {
return isStreamingResponseData(data, StreamingResponseDataType.FullFrame)
? fieldsOf(data)
: isStreamingResponseData(data, StreamingResponseDataType.NewValuesSameSchema)
? data.values
: response;
? data.values
: response;
})
)
).toEqual({

View File

@ -323,8 +323,8 @@ export function calculateHeatmapFromData(frames: DataFrame[], options: HeatmapCa
xBucketsCfg.mode === HeatmapCalculationMode.Size
? durationToMilliseconds(parseDuration(xBucketsCfg.value ?? ''))
: xBucketsCfg.value
? +xBucketsCfg.value
: undefined,
? +xBucketsCfg.value
: undefined,
yMode: yBucketsCfg.mode,
ySize: yBucketsCfg.value ? +yBucketsCfg.value : undefined,
yLog:

View File

@ -60,8 +60,8 @@ const AzureCheatSheet = (props: AzureCheatSheetProps) => {
return a.displayName.toLowerCase() === b.displayName.toLowerCase()
? 0
: a.displayName.toLowerCase() < b.displayName.toLowerCase()
? -1
: 1;
? -1
: 1;
});
const alphabetizedQueries = result.categories.reduce(
(queriesByCategory: CheatsheetQueries, category: Category) => {

View File

@ -56,8 +56,8 @@ export const AzureCredentialsForm = (props: Props) => {
const defaultAuthType = managedIdentityEnabled
? 'msi'
: workloadIdentityEnabled
? 'workloadidentity'
: 'clientsecret';
? 'workloadidentity'
: 'clientsecret';
const updated: AzureCredentials = {
...credentials,
authType: selected.value || defaultAuthType,

View File

@ -123,10 +123,10 @@ export function TimeManagement({ query, onQueryChange: onChange, schema }: Azure
query.azureLogAnalytics?.timeColumn
? query.azureLogAnalytics?.timeColumn
: defaultTimeColumns
? defaultTimeColumns[0]
: timeColumns
? timeColumns[0]
: { value: 'TimeGenerated', label: 'TimeGenerated' }
? defaultTimeColumns[0]
: timeColumns
? timeColumns[0]
: { value: 'TimeGenerated', label: 'TimeGenerated' }
}
allowCustomValue
/>

View File

@ -87,8 +87,9 @@ describe('CloudWatchLogsQueryRunner', () => {
it('should stop querying when timed out', async () => {
const { runner, queryMock } = setupMockedLogsQueryRunner();
const fakeFrames = genMockFrames(20);
const initialRecordsMatched = fakeFrames[0].meta!.stats!.find((stat) => stat.displayName === 'Records scanned')!
.value!;
const initialRecordsMatched = fakeFrames[0].meta!.stats!.find(
(stat) => stat.displayName === 'Records scanned'
)!.value!;
for (let i = 1; i < 4; i++) {
fakeFrames[i].meta!.stats = [
{
@ -98,8 +99,9 @@ describe('CloudWatchLogsQueryRunner', () => {
];
}
const finalRecordsMatched = fakeFrames[9].meta!.stats!.find((stat) => stat.displayName === 'Records scanned')!
.value!;
const finalRecordsMatched = fakeFrames[9].meta!.stats!.find(
(stat) => stat.displayName === 'Records scanned'
)!.value!;
for (let i = 10; i < fakeFrames.length; i++) {
fakeFrames[i].meta!.stats = [
{

View File

@ -95,8 +95,8 @@ export const AzureCredentialsForm = (props: Props) => {
const defaultAuthType = managedIdentityEnabled
? 'msi'
: workloadIdentityEnabled
? 'workloadidentity'
: 'clientsecret';
? 'workloadidentity'
: 'clientsecret';
const updated: AzureCredentials = {
...credentials,
authType: selected.value || defaultAuthType,

View File

@ -289,11 +289,11 @@ export function getConfig(opts: BarsOptions, theme: GrafanaTheme2) {
radius: pctStacked
? 0
: !isStacked
? barRadius
: (u: uPlot, seriesIdx: number) => {
let isTopmostSeries = seriesIdx === u.data.length - 1;
return isTopmostSeries ? [barRadius, 0] : [0, 0];
},
? barRadius
: (u: uPlot, seriesIdx: number) => {
let isTopmostSeries = seriesIdx === u.data.length - 1;
return isTopmostSeries ? [barRadius, 0] : [0, 0];
},
disp: {
x0: {
unit: 2,

View File

@ -79,8 +79,8 @@ export const FitMapViewEditor = ({ labelWidth, value, onChange, context }: Props
const currentDataScope = value.allLayers
? DataScopeValues.all
: !value.allLayers && value.lastOnly
? DataScopeValues.last
: DataScopeValues.layer;
? DataScopeValues.last
: DataScopeValues.layer;
const onDataScopeChange = (dataScope: DataScopeValues) => {
if (dataScope !== DataScopeValues.all && !value.layer) {

View File

@ -512,13 +512,13 @@ export function prepConfig(opts: PrepConfigOpts) {
dataRef.current?.xLayout === HeatmapCellLayout.le
? -1
: dataRef.current?.xLayout === HeatmapCellLayout.ge
? 1
: 0,
? 1
: 0,
yAlign: ((dataRef.current?.yLayout === HeatmapCellLayout.le
? -1
: dataRef.current?.yLayout === HeatmapCellLayout.ge
? 1
: 0) * (yAxisReverse ? -1 : 1)) as -1 | 0 | 1,
? 1
: 0) * (yAxisReverse ? -1 : 1)) as -1 | 0 | 1,
ySizeDivisor,
disp: {
fill: {
@ -975,8 +975,8 @@ export const valuesToFills = (values: number[], palette: string[], minValue: num
values[i] < minValue
? 0
: values[i] > maxValue
? paletteSize - 1
: Math.min(paletteSize - 1, Math.floor((paletteSize * (values[i] - minValue)) / range));
? paletteSize - 1
: Math.min(paletteSize - 1, Math.floor((paletteSize * (values[i] - minValue)) / range));
}
return indexedFills;

View File

@ -100,8 +100,8 @@ const prepConfig = (frame: DataFrame, theme: GrafanaTheme2) => {
distribution: isOrdinalX
? ScaleDistribution.Ordinal
: useLogScale
? ScaleDistribution.Log
: ScaleDistribution.Linear,
? ScaleDistribution.Log
: ScaleDistribution.Linear,
log: 2,
orientation: ScaleOrientation.Horizontal,
direction: ScaleDirection.Right,

View File

@ -305,8 +305,8 @@ const Nodes = memo(function Nodes(props: NodesProps) {
!props.hoveringIds || props.hoveringIds.length === 0
? 'default'
: props.hoveringIds?.includes(n.id)
? 'active'
: 'inactive'
? 'active'
: 'inactive'
}
/>
))}

View File

@ -17188,7 +17188,7 @@ __metadata:
postcss-loader: "npm:7.3.4"
postcss-reporter: "npm:7.1.0"
postcss-scss: "npm:4.0.9"
prettier: "npm:3.0.0"
prettier: "npm:3.2.4"
prismjs: "npm:1.29.0"
prop-types: "npm:15.8.1"
pseudoizer: "npm:^0.1.0"
@ -17279,7 +17279,7 @@ __metadata:
yaml: "npm:^2.0.0"
yargs: "npm:^17.5.1"
dependenciesMeta:
prettier@3.0.0:
prettier@3.2.4:
unplugged: true
languageName: unknown
linkType: soft
@ -23702,12 +23702,12 @@ __metadata:
languageName: node
linkType: hard
"prettier@npm:3.0.0":
version: 3.0.0
resolution: "prettier@npm:3.0.0"
"prettier@npm:3.2.4":
version: 3.2.4
resolution: "prettier@npm:3.2.4"
bin:
prettier: bin/prettier.cjs
checksum: 399292638280988ecd44db6532e908246b7c9468e6f5f571b3835a5206b7f1132cb674c12be430d921474901dc85398429dfd2dc31b282eef9affebd3ce72cef
checksum: e2b735d0552501b3a7ac8bd3ba3b6de2920bb35bd4cd02d08cb9057ebe3e96d83b9a7e4b903d987b7530a50223b12c74d107c154337236ae2c68156ba1e65cd2
languageName: node
linkType: hard