mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Monaco Editor: Load via ESM (#78261)
* chore(monaco): bump monaco-editor to latest version * feat(codeeditor): use esm to load monaco editor * revert(monaco): put back previous version * feat(monaco): setup MonacoEnvironment when bootstrapping app * feat(monaco): load monaco languages from registry as workers * feat(webpack): clean up warnings, remove need to copy monaco into lib * fix(plugins): wip - remove amd loader workaround in systemjs hooks * chore(azure): clean up so QueryField passes typecheck * test(jest): update config to fix failing tests due to missing monaco-editor * test(jest): update config to work with monaco-editor and kusto * test(jest): prevent message eventlistener in nodeGraph/layout.worker tripping up monaco tests * test(plugins): wip - remove amd related tests from systemjs hooks * test(alerting): prefer clearAllMocks to prevent monaco editor failing due to missing matchMedia * test(parca): fix failing test due to undefined backendSrv * chore: move monacoEnv to app/core * test: increase testing-lib timeout to 2secs, fix parca test to assert dom element * feat(plugins): share kusto via systemjs * test(e2e): increase timeout for checking monaco editor in exemplars spec * test(e2e): assert monaco has loaded by checking the spinner is gone and window.monaco exists * test(e2e): check for monaco editor textarea * test(e2e): check monaco editor is loaded before assertions * test(e2e): add waitForMonacoToLoad util to reduce duplication * test(e2e): fix failing mysql spec * chore(jest): add comment to setupTests explaining need to incresae default timeout * chore(nodegraph): improve comment in layout.worker.utils to better explain the need for file
This commit is contained in:
parent
0dbf2da254
commit
0dcdfc261b
@ -4581,10 +4581,6 @@ exports[`better eslint`] = {
|
||||
"public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.ts:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
],
|
||||
"public/app/plugins/datasource/azuremonitor/components/LogsQueryEditor/QueryField.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
||||
],
|
||||
"public/app/plugins/datasource/azuremonitor/components/QueryEditor/QueryEditor.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
],
|
||||
|
7
e2e/utils/support/monaco.ts
Normal file
7
e2e/utils/support/monaco.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { e2e } from '../index';
|
||||
|
||||
export function waitForMonacoToLoad() {
|
||||
e2e.components.QueryField.container().children('[data-testid="Spinner"]').should('not.exist');
|
||||
cy.window().its('monaco').should('exist');
|
||||
cy.get('.monaco-editor textarea:first').should('exist');
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import { e2e } from '../utils';
|
||||
import { waitForMonacoToLoad } from '../utils/support/monaco';
|
||||
|
||||
const dataSourceName = 'PromExemplar';
|
||||
const addDataSource = () => {
|
||||
@ -57,12 +58,8 @@ describe('Exemplars', () => {
|
||||
// Switch to code editor
|
||||
e2e.components.RadioButton.container().filter(':contains("Code")').click();
|
||||
|
||||
// we need to wait for the query-field being lazy-loaded, in two steps:
|
||||
// 1. first we wait for the text 'Loading...' to appear
|
||||
// 1. then we wait for the text 'Loading...' to disappear
|
||||
const monacoLoadingText = 'Loading...';
|
||||
e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
|
||||
e2e.components.QueryField.container().should('be.visible').should('not.have.text', monacoLoadingText);
|
||||
// Wait for lazy loading Monaco
|
||||
waitForMonacoToLoad();
|
||||
|
||||
e2e.components.TimePicker.openButton().click();
|
||||
e2e.components.TimePicker.fromField().clear().type('2021-07-10 17:10:00');
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { e2e } from '../utils';
|
||||
import { waitForMonacoToLoad } from '../utils/support/monaco';
|
||||
|
||||
const dataSourceName = 'LokiEditor';
|
||||
const addDataSource = () => {
|
||||
@ -39,11 +40,7 @@ describe('Loki Query Editor', () => {
|
||||
|
||||
e2e.components.RadioButton.container().filter(':contains("Code")').click();
|
||||
|
||||
// Wait for lazy loading
|
||||
const monacoLoadingText = 'Loading...';
|
||||
|
||||
e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
|
||||
e2e.components.QueryField.container().should('be.visible').should('not.have.text', monacoLoadingText);
|
||||
waitForMonacoToLoad();
|
||||
|
||||
// adds closing braces around empty value
|
||||
e2e.components.QueryField.container().type('time(');
|
||||
|
@ -37,6 +37,9 @@ describe('MySQL datasource', () => {
|
||||
it.skip('code editor autocomplete should handle table name escaping/quoting', () => {
|
||||
e2e.components.RadioButton.container().filter(':contains("Code")').click();
|
||||
|
||||
e2e.components.CodeEditor.container().children('[data-testid="Spinner"]').should('not.exist');
|
||||
cy.window().its('monaco').should('exist');
|
||||
|
||||
cy.get('textarea').type('S{downArrow}{enter}');
|
||||
cy.wait('@tables');
|
||||
cy.get('.suggest-widget').contains(tableNameWithSpecialCharacter).should('be.visible');
|
||||
@ -88,8 +91,10 @@ describe('MySQL datasource', () => {
|
||||
cy.get("[aria-label='Macros value selector']").should('be.visible').click();
|
||||
selectOption('timeFilter');
|
||||
|
||||
// Validate that the timeFilter macro was added
|
||||
e2e.components.CodeEditor.container().children('[data-testid="Spinner"]').should('not.exist');
|
||||
cy.window().its('monaco').should('exist');
|
||||
|
||||
// Validate that the timeFilter macro was added
|
||||
e2e.components.CodeEditor.container()
|
||||
.get('textarea')
|
||||
.should(
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { e2e } from '../utils';
|
||||
import { waitForMonacoToLoad } from '../utils/support/monaco';
|
||||
|
||||
describe('Query editor', () => {
|
||||
beforeEach(() => {
|
||||
@ -14,13 +15,8 @@ describe('Query editor', () => {
|
||||
|
||||
e2e.components.RadioButton.container().filter(':contains("Code")').click();
|
||||
|
||||
// we need to wait for the query-field being lazy-loaded, in two steps:
|
||||
// it is a two-step process:
|
||||
// 1. first we wait for the text 'Loading...' to appear
|
||||
// 1. then we wait for the text 'Loading...' to disappear
|
||||
const monacoLoadingText = 'Loading...';
|
||||
e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
|
||||
e2e.components.QueryField.container().should('be.visible').should('not.have.text', monacoLoadingText);
|
||||
waitForMonacoToLoad();
|
||||
|
||||
e2e.components.QueryField.container().type(queryText, { parseSpecialCharSequences: false }).type('{backspace}');
|
||||
|
||||
cy.contains(queryText.slice(0, -1)).should('be.visible');
|
||||
|
@ -15,6 +15,9 @@ const esModules = [
|
||||
'leven',
|
||||
'nanoid',
|
||||
'monaco-promql',
|
||||
'@kusto/monaco-kusto',
|
||||
'monaco-editor',
|
||||
'lodash-es',
|
||||
].join('|');
|
||||
|
||||
module.exports = {
|
||||
@ -41,7 +44,9 @@ module.exports = {
|
||||
'\\.svg': '<rootDir>/public/test/mocks/svg.ts',
|
||||
'\\.css': '<rootDir>/public/test/mocks/style.ts',
|
||||
'react-inlinesvg': '<rootDir>/public/test/mocks/react-inlinesvg.tsx',
|
||||
'monaco-editor/esm/vs/editor/editor.api': '<rootDir>/public/test/mocks/monaco.ts',
|
||||
// resolve directly as monaco and kusto don't have main property in package.json which jest needs
|
||||
'^monaco-editor$': 'monaco-editor/esm/vs/editor/editor.api.js',
|
||||
'@kusto/monaco-kusto': '@kusto/monaco-kusto/release/esm/monaco.contribution.js',
|
||||
// near-membrane-dom won't work in a nodejs environment.
|
||||
'@locker/near-membrane-dom': '<rootDir>/public/test/mocks/nearMembraneDom.ts',
|
||||
'^@grafana/schema/dist/esm/(.*)$': '<rootDir>/packages/grafana-schema/src/$1',
|
||||
|
@ -4,7 +4,7 @@ import { Registry, RegistryItem } from '../utils/Registry';
|
||||
* @alpha
|
||||
*/
|
||||
export interface MonacoLanguageRegistryItem extends RegistryItem {
|
||||
init: () => Promise<void>;
|
||||
init: () => Worker;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,11 +62,3 @@ export function getPluginImportUtils(): PluginImportUtils {
|
||||
|
||||
return pluginImportUtils;
|
||||
}
|
||||
|
||||
// Grafana relies on RequireJS for Monaco Editor to load.
|
||||
// The SystemJS AMD extra creates a global define which causes RequireJS to silently bail.
|
||||
// Here we move and reset global define so Monaco Editor loader script continues to work.
|
||||
// @ts-ignore
|
||||
window.__grafana_amd_define = window.define;
|
||||
// @ts-ignore
|
||||
window.define = undefined;
|
||||
|
@ -119,14 +119,12 @@ class UnthemedCodeEditor extends PureComponent<Props> {
|
||||
}
|
||||
});
|
||||
|
||||
const languagePromise = this.loadCustomLanguage();
|
||||
|
||||
if (onChange) {
|
||||
editor.getModel()?.onDidChangeContent(() => onChange(editor.getValue()));
|
||||
}
|
||||
|
||||
if (onEditorDidMount) {
|
||||
languagePromise.then(() => onEditorDidMount(editor, monaco));
|
||||
onEditorDidMount(editor, monaco);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import MonacoEditor, { loader as monacoEditorLoader, Monaco } from '@monaco-editor/react';
|
||||
import Editor, { loader as monacoEditorLoader, Monaco } from '@monaco-editor/react';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { useTheme2 } from '../../themes';
|
||||
@ -6,11 +7,8 @@ import { useTheme2 } from '../../themes';
|
||||
import defineThemes from './theme';
|
||||
import type { ReactMonacoEditorProps } from './types';
|
||||
|
||||
monacoEditorLoader.config({
|
||||
paths: {
|
||||
vs: (window.__grafana_public_path__ ?? 'public/') + 'lib/monaco/min/vs',
|
||||
},
|
||||
});
|
||||
// pass the monaco editor to the loader to bypass requirejs
|
||||
monacoEditorLoader.config({ monaco });
|
||||
|
||||
export const ReactMonacoEditor = (props: ReactMonacoEditorProps) => {
|
||||
const { beforeMount } = props;
|
||||
@ -25,10 +23,6 @@ export const ReactMonacoEditor = (props: ReactMonacoEditorProps) => {
|
||||
);
|
||||
|
||||
return (
|
||||
<MonacoEditor
|
||||
{...props}
|
||||
theme={theme.isDark ? 'grafana-dark' : 'grafana-light'}
|
||||
beforeMount={onMonacoBeforeMount}
|
||||
/>
|
||||
<Editor {...props} theme={theme.isDark ? 'grafana-dark' : 'grafana-light'} beforeMount={onMonacoBeforeMount} />
|
||||
);
|
||||
};
|
||||
|
@ -56,6 +56,7 @@ import { PluginPage } from './core/components/Page/PluginPage';
|
||||
import { GrafanaContextType, useReturnToPreviousInternal } from './core/context/GrafanaContext';
|
||||
import { initIconCache } from './core/icons/iconBundle';
|
||||
import { initializeI18n } from './core/internationalization';
|
||||
import { setMonacoEnv } from './core/monacoEnv';
|
||||
import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks';
|
||||
import { ModalManager } from './core/services/ModalManager';
|
||||
import { NewFrontendAssetsChecker } from './core/services/NewFrontendAssetsChecker';
|
||||
@ -170,7 +171,9 @@ export class GrafanaApp {
|
||||
createAdHocVariableAdapter(),
|
||||
createSystemVariableAdapter(),
|
||||
]);
|
||||
|
||||
monacoLanguageRegistry.setInit(getDefaultMonacoLanguages);
|
||||
setMonacoEnv();
|
||||
|
||||
setQueryRunnerFactory(() => new QueryRunner());
|
||||
setVariableQueryRunner(new VariableQueryRunner());
|
||||
|
32
public/app/core/monacoEnv.ts
Normal file
32
public/app/core/monacoEnv.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { monacoLanguageRegistry } from '@grafana/data';
|
||||
import { CorsWorker as Worker } from 'app/core/utils/CorsWorker';
|
||||
|
||||
export function setMonacoEnv() {
|
||||
self.MonacoEnvironment = {
|
||||
getWorker(_moduleId, label) {
|
||||
const language = monacoLanguageRegistry.getIfExists(label);
|
||||
|
||||
if (language) {
|
||||
return language.init();
|
||||
}
|
||||
|
||||
if (label === 'json') {
|
||||
return new Worker(new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url));
|
||||
}
|
||||
|
||||
if (label === 'css' || label === 'scss' || label === 'less') {
|
||||
return new Worker(new URL('monaco-editor/esm/vs/language/css/css.worker', import.meta.url));
|
||||
}
|
||||
|
||||
if (label === 'html' || label === 'handlebars' || label === 'razor') {
|
||||
return new Worker(new URL('monaco-editor/esm/vs/language/html/html.worker', import.meta.url));
|
||||
}
|
||||
|
||||
if (label === 'typescript' || label === 'javascript') {
|
||||
return new Worker(new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url));
|
||||
}
|
||||
|
||||
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url));
|
||||
},
|
||||
};
|
||||
}
|
@ -89,7 +89,7 @@ const ui = {
|
||||
|
||||
describe('Admin config', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.clearAllMocks();
|
||||
// FIXME: scope down
|
||||
grantUserPermissions(Object.values(AccessControlAction));
|
||||
mocks.getAllDataSources.mockReturnValue(Object.values(dataSources));
|
||||
|
@ -1,5 +1,3 @@
|
||||
export const SHARED_DEPENDENCY_PREFIX = 'package';
|
||||
export const LOAD_PLUGIN_CSS_REGEX = /^plugins.+\.css$/i;
|
||||
export const JS_CONTENT_TYPE_REGEX = /^(text|application)\/(x-)?javascript(;|$)/;
|
||||
export const AMD_MODULE_REGEX =
|
||||
/(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF.])define\s*\(\s*("[^"]+"\s*,\s*|'[^']+'\s*,\s*)?\s*(\[(\s*(("[^"]+"|'[^']+')\s*,|\/\/.*\r?\n))*(\s*("[^"]+"|'[^']+')\s*,?)?(\s*(\/\/.*\r?\n|\/\*\/))*\s*\]|function\s*|{|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*\))/;
|
||||
|
@ -23,68 +23,6 @@ export const mockAmdModule = `define([], function() {
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockAmdModuleNamedNoDeps = `define("named", function() {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockAmdModuleNamedWithDeps = `define("named", ["dep"], function(dep) {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockAmdModuleNamedWithDeps2 = `define("named", ["dep", "dep2"], function(dep, dep2) {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockAmdModuleNamedWithDeps3 = `define("named", ["dep",
|
||||
"dep2"
|
||||
], function(dep, dep2) {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockAmdModuleOnlyFunction = `define(function() {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockAmdModuleWithComments = `/*! For license information please see module.js.LICENSE.txt */
|
||||
define(function(react) {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockAmdModuleWithComments2 = `/*! This is a commment */
|
||||
define(["dep"],
|
||||
/*! This is a commment */
|
||||
function(dep) {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
export const mockModuleWithDefineMethod = `ace.define(function() {
|
||||
return function() {
|
||||
console.log('AMD module loaded');
|
||||
var pluginPath = "/public/plugins/";
|
||||
}
|
||||
});`;
|
||||
|
||||
const server = setupServer(
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModule/module.js',
|
||||
@ -112,78 +50,6 @@ const server = setupServer(
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModuleNamedNoDeps/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockAmdModuleNamedNoDeps, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModuleNamedWithDeps/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockAmdModuleNamedWithDeps, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModuleNamedWithDeps2/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockAmdModuleNamedWithDeps2, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModuleNamedWithDeps3/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockAmdModuleNamedWithDeps3, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModuleOnlyFunction/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockAmdModuleOnlyFunction, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModuleWithComments/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockAmdModuleWithComments, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockAmdModuleWithComments2/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockAmdModuleWithComments2, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
),
|
||||
http.get(
|
||||
'/public/plugins/mockModuleWithDefineMethod/module.js',
|
||||
() =>
|
||||
new HttpResponse(mockModuleWithDefineMethod, {
|
||||
headers: {
|
||||
'Content-Type': 'text/javascript',
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as emotion from '@emotion/css';
|
||||
import * as emotionReact from '@emotion/react';
|
||||
import * as kusto from '@kusto/monaco-kusto';
|
||||
import * as d3 from 'd3';
|
||||
import * as i18next from 'i18next';
|
||||
import jquery from 'jquery';
|
||||
@ -71,6 +72,7 @@ export const sharedDependenciesMap: Record<string, System.Module> = {
|
||||
'@grafana/runtime': grafanaRuntime,
|
||||
'@grafana/slate-react': slateReact, // for backwards compatibility with older plugins
|
||||
'@grafana/ui': grafanaUI,
|
||||
'@kusto/monaco-kusto': kusto,
|
||||
'app/core/app_events': {
|
||||
default: appEvents,
|
||||
__useDefault: true,
|
||||
|
@ -7,19 +7,7 @@ jest.mock('./cache', () => ({
|
||||
resolveWithCache: (url: string) => `${url}?_cache=1234`,
|
||||
}));
|
||||
|
||||
import {
|
||||
server,
|
||||
mockAmdModule,
|
||||
mockSystemModule,
|
||||
mockAmdModuleNamedNoDeps,
|
||||
mockAmdModuleNamedWithDeps,
|
||||
mockAmdModuleNamedWithDeps2,
|
||||
mockAmdModuleNamedWithDeps3,
|
||||
mockAmdModuleOnlyFunction,
|
||||
mockAmdModuleWithComments,
|
||||
mockModuleWithDefineMethod,
|
||||
mockAmdModuleWithComments2,
|
||||
} from './pluginLoader.mock';
|
||||
import { server } from './pluginLoader.mock';
|
||||
import { decorateSystemJSFetch, decorateSystemJSResolve } from './systemjsHooks';
|
||||
import { SystemJSWithLoaderHooks } from './types';
|
||||
|
||||
@ -44,116 +32,6 @@ describe('SystemJS Loader Hooks', () => {
|
||||
});
|
||||
|
||||
describe('decorateSystemJSFetch', () => {
|
||||
it('wraps AMD modules in an AMD iife', async () => {
|
||||
const basicResult = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModule/module.js',
|
||||
{}
|
||||
);
|
||||
const basicSource = await basicResult.text();
|
||||
const basicExpected = `(function(define) {
|
||||
${mockAmdModule}
|
||||
})(window.__grafana_amd_define);`;
|
||||
expect(basicSource).toBe(basicExpected);
|
||||
|
||||
const mockAmdModuleNamedNoDepsResult = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModuleNamedNoDeps/module.js',
|
||||
{}
|
||||
);
|
||||
const mockAmdModuleNamedNoDepsSource = await mockAmdModuleNamedNoDepsResult.text();
|
||||
const mockAmdModuleNamedNoDepsExpected = `(function(define) {
|
||||
${mockAmdModuleNamedNoDeps}
|
||||
})(window.__grafana_amd_define);`;
|
||||
|
||||
expect(mockAmdModuleNamedNoDepsSource).toBe(mockAmdModuleNamedNoDepsExpected);
|
||||
|
||||
const mockAmdModuleNamedWithDepsResult = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModuleNamedWithDeps/module.js',
|
||||
{}
|
||||
);
|
||||
const mockAmdModuleNamedWithDepsSource = await mockAmdModuleNamedWithDepsResult.text();
|
||||
const mockAmdModuleNamedWithDepsExpected = `(function(define) {
|
||||
${mockAmdModuleNamedWithDeps}
|
||||
})(window.__grafana_amd_define);`;
|
||||
|
||||
expect(mockAmdModuleNamedWithDepsSource).toBe(mockAmdModuleNamedWithDepsExpected);
|
||||
|
||||
const mockAmdModuleNamedWithDeps2Result = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModuleNamedWithDeps2/module.js',
|
||||
{}
|
||||
);
|
||||
const mockAmdModuleNamedWithDeps2Source = await mockAmdModuleNamedWithDeps2Result.text();
|
||||
const mockAmdModuleNamedWithDeps2Expected = `(function(define) {
|
||||
${mockAmdModuleNamedWithDeps2}
|
||||
})(window.__grafana_amd_define);`;
|
||||
|
||||
expect(mockAmdModuleNamedWithDeps2Source).toBe(mockAmdModuleNamedWithDeps2Expected);
|
||||
|
||||
const mockAmdModuleNamedWithDeps3Result = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModuleNamedWithDeps3/module.js',
|
||||
{}
|
||||
);
|
||||
const mockAmdModuleNamedWithDeps3Source = await mockAmdModuleNamedWithDeps3Result.text();
|
||||
const mockAmdModuleNamedWithDeps3Expected = `(function(define) {
|
||||
${mockAmdModuleNamedWithDeps3}
|
||||
})(window.__grafana_amd_define);`;
|
||||
|
||||
expect(mockAmdModuleNamedWithDeps3Source).toBe(mockAmdModuleNamedWithDeps3Expected);
|
||||
|
||||
const mockAmdModuleOnlyFunctionResult = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModuleOnlyFunction/module.js',
|
||||
{}
|
||||
);
|
||||
const mockAmdModuleOnlyFunctionSource = await mockAmdModuleOnlyFunctionResult.text();
|
||||
const mockAmdModuleOnlyFunctionExpected = `(function(define) {
|
||||
${mockAmdModuleOnlyFunction}
|
||||
})(window.__grafana_amd_define);`;
|
||||
|
||||
expect(mockAmdModuleOnlyFunctionSource).toBe(mockAmdModuleOnlyFunctionExpected);
|
||||
|
||||
const mockAmdModuleWithCommentsResult = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModuleWithComments/module.js',
|
||||
{}
|
||||
);
|
||||
const mockAmdModuleWithCommentsSource = await mockAmdModuleWithCommentsResult.text();
|
||||
const mockAmdModuleWithCommentsExpected = `(function(define) {
|
||||
${mockAmdModuleWithComments}
|
||||
})(window.__grafana_amd_define);`;
|
||||
|
||||
expect(mockAmdModuleWithCommentsSource).toBe(mockAmdModuleWithCommentsExpected);
|
||||
|
||||
const mockAmdModuleWithComments2Result = await decorateSystemJSFetch(
|
||||
systemJSPrototype.fetch,
|
||||
'/public/plugins/mockAmdModuleWithComments2/module.js',
|
||||
{}
|
||||
);
|
||||
const mockAmdModuleWithComments2Source = await mockAmdModuleWithComments2Result.text();
|
||||
const mockAmdModuleWithComments2Expected = `(function(define) {
|
||||
${mockAmdModuleWithComments2}
|
||||
})(window.__grafana_amd_define);`;
|
||||
|
||||
expect(mockAmdModuleWithComments2Source).toBe(mockAmdModuleWithComments2Expected);
|
||||
});
|
||||
it("doesn't wrap system modules in an AMD iife", async () => {
|
||||
const url = '/public/plugins/mockSystemModule/module.js';
|
||||
const result = await decorateSystemJSFetch(systemJSPrototype.fetch, url, {});
|
||||
const source = await result.text();
|
||||
|
||||
expect(source).toBe(mockSystemModule);
|
||||
});
|
||||
it("doesn't wrap modules with a define method in an AMD iife", async () => {
|
||||
const url = '/public/plugins/mockModuleWithDefineMethod/module.js';
|
||||
const result = await decorateSystemJSFetch(systemJSPrototype.fetch, url, {});
|
||||
const source = await result.text();
|
||||
|
||||
expect(source).toBe(mockModuleWithDefineMethod);
|
||||
});
|
||||
it('only transforms plugin source code hosted on cdn with cdn paths', async () => {
|
||||
config.pluginsCDNBaseURL = 'http://my-cdn.com/plugins';
|
||||
const cdnUrl = 'http://my-cdn.com/plugins/my-plugin/v1.0.0/public/plugins/my-plugin/module.js';
|
||||
|
@ -3,7 +3,7 @@ import { config, SystemJS } from '@grafana/runtime';
|
||||
import { transformPluginSourceForCDN } from '../cdn/utils';
|
||||
|
||||
import { resolveWithCache } from './cache';
|
||||
import { LOAD_PLUGIN_CSS_REGEX, JS_CONTENT_TYPE_REGEX, AMD_MODULE_REGEX, SHARED_DEPENDENCY_PREFIX } from './constants';
|
||||
import { LOAD_PLUGIN_CSS_REGEX, JS_CONTENT_TYPE_REGEX, SHARED_DEPENDENCY_PREFIX } from './constants';
|
||||
import { SystemJSWithLoaderHooks } from './types';
|
||||
import { isHostedOnCDN } from './utils';
|
||||
|
||||
@ -19,10 +19,6 @@ export async function decorateSystemJSFetch(
|
||||
const source = await res.text();
|
||||
let transformedSrc = source;
|
||||
|
||||
if (AMD_MODULE_REGEX.test(transformedSrc)) {
|
||||
transformedSrc = preventAMDLoaderCollision(source);
|
||||
}
|
||||
|
||||
// JS files on the CDN need their asset paths transformed in the source
|
||||
if (isHostedOnCDN(res.url)) {
|
||||
const cdnTransformedSrc = transformPluginSourceForCDN({ url: res.url, source: transformedSrc });
|
||||
@ -84,11 +80,3 @@ function getBackWardsCompatibleUrl(url: string) {
|
||||
|
||||
return hasValidFileExtension ? url : url + '.js';
|
||||
}
|
||||
|
||||
// This transform prevents a conflict between systemjs and requirejs which Monaco Editor
|
||||
// depends on. See packages/grafana-runtime/src/utils/plugin.ts for more.
|
||||
function preventAMDLoaderCollision(source: string) {
|
||||
return `(function(define) {
|
||||
${source}
|
||||
})(window.__grafana_amd_define);`;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { EngineSchema, Schema } from '@kusto/monaco-kusto';
|
||||
import { Uri } from 'monaco-editor';
|
||||
import { EngineSchema, getKustoWorker } from '@kusto/monaco-kusto';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { CodeEditor, Monaco, MonacoEditor } from '@grafana/ui';
|
||||
@ -13,16 +12,6 @@ interface MonacoEditorValues {
|
||||
monaco: Monaco;
|
||||
}
|
||||
|
||||
interface MonacoLanguages {
|
||||
kusto: {
|
||||
getKustoWorker: () => Promise<
|
||||
(url: Uri) => Promise<{
|
||||
setSchema: (schema: Schema) => void;
|
||||
}>
|
||||
>;
|
||||
};
|
||||
}
|
||||
|
||||
const QueryField = ({ query, onQueryChange, schema }: AzureQueryEditorFieldProps) => {
|
||||
const [monaco, setMonaco] = useState<MonacoEditorValues | undefined>();
|
||||
|
||||
@ -33,10 +22,9 @@ const QueryField = ({ query, onQueryChange, schema }: AzureQueryEditorFieldProps
|
||||
|
||||
const setupEditor = async ({ monaco, editor }: MonacoEditorValues, schema: EngineSchema) => {
|
||||
try {
|
||||
const languages = monaco.languages as unknown as MonacoLanguages;
|
||||
const model = editor.getModel();
|
||||
if (model) {
|
||||
const kustoWorker = await languages.kusto.getKustoWorker();
|
||||
const kustoWorker = await getKustoWorker();
|
||||
const kustoMode = await kustoWorker(model?.uri);
|
||||
await kustoMode.setSchema(schema);
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import React from 'react';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { CoreApp, DataSourcePluginMeta, PluginType } from '@grafana/data';
|
||||
import { BackendSrv, getBackendSrv, setBackendSrv } from '@grafana/runtime';
|
||||
|
||||
import { ParcaDataSource } from '../datasource';
|
||||
import { ProfileTypeMessage } from '../types';
|
||||
@ -10,6 +12,17 @@ import { ProfileTypeMessage } from '../types';
|
||||
import { Props, QueryEditor } from './QueryEditor';
|
||||
|
||||
describe('QueryEditor', () => {
|
||||
let origBackendSrv: BackendSrv;
|
||||
const fetchMock = jest.fn().mockReturnValue(of({ data: [] }));
|
||||
|
||||
beforeEach(() => {
|
||||
origBackendSrv = getBackendSrv();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
setBackendSrv(origBackendSrv);
|
||||
});
|
||||
|
||||
it('should render without error', async () => {
|
||||
setup();
|
||||
|
||||
@ -17,6 +30,7 @@ describe('QueryEditor', () => {
|
||||
});
|
||||
|
||||
it('should render options', async () => {
|
||||
setBackendSrv({ ...origBackendSrv, fetch: fetchMock });
|
||||
setup();
|
||||
await openOptions();
|
||||
expect(screen.getByText(/Metric/)).toBeDefined();
|
||||
@ -25,6 +39,7 @@ describe('QueryEditor', () => {
|
||||
});
|
||||
|
||||
it('should render correct options outside of explore', async () => {
|
||||
setBackendSrv({ ...origBackendSrv, fetch: fetchMock });
|
||||
setup({ props: { app: CoreApp.Dashboard } });
|
||||
await openOptions();
|
||||
expect(screen.getByText(/Metric/)).toBeDefined();
|
||||
|
@ -1,176 +1,7 @@
|
||||
import { forceSimulation, forceLink, forceCollide, forceX } from 'd3-force';
|
||||
import { layout } from './layout.worker.utils';
|
||||
|
||||
addEventListener('message', (event) => {
|
||||
const { nodes, edges, config } = event.data;
|
||||
layout(nodes, edges, config);
|
||||
postMessage({ nodes, edges });
|
||||
});
|
||||
|
||||
/**
|
||||
* Use d3 force layout to lay the nodes in a sensible way. This function modifies the nodes adding the x,y positions
|
||||
* and also fills in node references in edges instead of node ids.
|
||||
*/
|
||||
export function layout(nodes, edges, config) {
|
||||
// Start with some hardcoded positions so it starts laid out from left to right
|
||||
let { roots, secondLevelRoots } = initializePositions(nodes, edges);
|
||||
|
||||
// There always seems to be one or more root nodes each with single edge and we want to have them static on the
|
||||
// left neatly in something like grid layout
|
||||
[...roots, ...secondLevelRoots].forEach((n, index) => {
|
||||
n.fx = n.x;
|
||||
});
|
||||
|
||||
const simulation = forceSimulation(nodes)
|
||||
.force(
|
||||
'link',
|
||||
forceLink(edges)
|
||||
.id((d) => d.id)
|
||||
.distance(config.linkDistance)
|
||||
.strength(config.linkStrength)
|
||||
)
|
||||
// to keep the left to right layout we add force that pulls all nodes to right but because roots are fixed it will
|
||||
// apply only to non root nodes
|
||||
.force('x', forceX(config.forceX).strength(config.forceXStrength))
|
||||
// Make sure nodes don't overlap
|
||||
.force('collide', forceCollide(config.forceCollide));
|
||||
|
||||
// 300 ticks for the simulation are recommended but less would probably work too, most movement is done in first
|
||||
// few iterations and then all the forces gets smaller https://github.com/d3/d3-force#simulation_alphaDecay
|
||||
simulation.tick(config.tick);
|
||||
simulation.stop();
|
||||
|
||||
// We do centering here instead of using centering force to keep this more stable
|
||||
centerNodes(nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* This initializes positions of the graph by going from the root to its children and laying it out in a grid from left
|
||||
* to right. This works only so, so because service map graphs can have cycles and children levels are not ordered in a
|
||||
* way to minimize the edge lengths. Nevertheless this seems to make the graph easier to nudge with the forces later on
|
||||
* than with the d3 default initial positioning. Also we can fix the root positions later on for a bit more neat
|
||||
* organisation.
|
||||
*
|
||||
* This function directly modifies the nodes given and only returns references to root nodes so they do not have to be
|
||||
* found again later on.
|
||||
*
|
||||
* How the spacing could look like approximately:
|
||||
* 0 - 0 - 0 - 0
|
||||
* \- 0 - 0 |
|
||||
* \- 0 -/
|
||||
* 0 - 0 -/
|
||||
*/
|
||||
function initializePositions(nodes, edges) {
|
||||
// To prevent going in cycles
|
||||
const alreadyPositioned = {};
|
||||
|
||||
const nodesMap = nodes.reduce((acc, node) => {
|
||||
acc[node.id] = node;
|
||||
return acc;
|
||||
}, {});
|
||||
const edgesMap = edges.reduce((acc, edge) => {
|
||||
const sourceId = edge.source;
|
||||
acc[sourceId] = [...(acc[sourceId] || []), edge];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
let roots = nodes.filter((n) => n.incoming === 0);
|
||||
|
||||
// For things like service maps we assume there is some root (client) node but if there is none then selecting
|
||||
// any node as a starting point should work the same.
|
||||
if (!roots.length) {
|
||||
roots = [nodes[0]];
|
||||
}
|
||||
|
||||
let secondLevelRoots = roots.reduce((acc, r) => {
|
||||
acc.push(...(edgesMap[r.id] ? edgesMap[r.id].map((e) => nodesMap[e.target]) : []));
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const rootYSpacing = 300;
|
||||
const nodeYSpacing = 200;
|
||||
const nodeXSpacing = 200;
|
||||
|
||||
let rootY = 0;
|
||||
for (const root of roots) {
|
||||
let graphLevel = [root];
|
||||
let x = 0;
|
||||
while (graphLevel.length > 0) {
|
||||
const nextGraphLevel = [];
|
||||
let y = rootY;
|
||||
for (const node of graphLevel) {
|
||||
if (alreadyPositioned[node.id]) {
|
||||
continue;
|
||||
}
|
||||
// Initialize positions based on the spacing in the grid
|
||||
node.x = x;
|
||||
node.y = y;
|
||||
alreadyPositioned[node.id] = true;
|
||||
|
||||
// Move to next Y position for next node
|
||||
y += nodeYSpacing;
|
||||
if (edgesMap[node.id]) {
|
||||
nextGraphLevel.push(...edgesMap[node.id].map((edge) => nodesMap[edge.target]));
|
||||
}
|
||||
}
|
||||
|
||||
graphLevel = nextGraphLevel;
|
||||
// Move to next X position for next level
|
||||
x += nodeXSpacing;
|
||||
// Reset Y back to baseline for this root
|
||||
y = rootY;
|
||||
}
|
||||
rootY += rootYSpacing;
|
||||
}
|
||||
return { roots, secondLevelRoots };
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the center of the graph based on its bound is in 0, 0 coordinates.
|
||||
* Modifies the nodes directly.
|
||||
*/
|
||||
function centerNodes(nodes) {
|
||||
const bounds = graphBounds(nodes);
|
||||
for (let node of nodes) {
|
||||
node.x = node.x - bounds.center.x;
|
||||
node.y = node.y - bounds.center.y;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bounds of the graph meaning the extent of the nodes in all directions.
|
||||
*/
|
||||
function graphBounds(nodes) {
|
||||
if (nodes.length === 0) {
|
||||
return { top: 0, right: 0, bottom: 0, left: 0, center: { x: 0, y: 0 } };
|
||||
}
|
||||
|
||||
const bounds = nodes.reduce(
|
||||
(acc, node) => {
|
||||
if (node.x > acc.right) {
|
||||
acc.right = node.x;
|
||||
}
|
||||
if (node.x < acc.left) {
|
||||
acc.left = node.x;
|
||||
}
|
||||
if (node.y > acc.bottom) {
|
||||
acc.bottom = node.y;
|
||||
}
|
||||
if (node.y < acc.top) {
|
||||
acc.top = node.y;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ top: Infinity, right: -Infinity, bottom: -Infinity, left: Infinity }
|
||||
);
|
||||
|
||||
const y = bounds.top + (bounds.bottom - bounds.top) / 2;
|
||||
const x = bounds.left + (bounds.right - bounds.left) / 2;
|
||||
|
||||
return {
|
||||
...bounds,
|
||||
center: {
|
||||
x,
|
||||
y,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
174
public/app/plugins/panel/nodeGraph/layout.worker.utils.js
Normal file
174
public/app/plugins/panel/nodeGraph/layout.worker.utils.js
Normal file
@ -0,0 +1,174 @@
|
||||
// This file is a workaround so the layout function can be imported in Jest mocks. If the jest mock imports the
|
||||
// layout.worker.js file it will attach the eventlistener and then call the layout function with undefined data
|
||||
// which causes tests to fail.
|
||||
|
||||
import { forceSimulation, forceLink, forceCollide, forceX } from 'd3-force';
|
||||
|
||||
/**
|
||||
* Use d3 force layout to lay the nodes in a sensible way. This function modifies the nodes adding the x,y positions
|
||||
* and also fills in node references in edges instead of node ids.
|
||||
*/
|
||||
export function layout(nodes, edges, config) {
|
||||
// Start with some hardcoded positions so it starts laid out from left to right
|
||||
let { roots, secondLevelRoots } = initializePositions(nodes, edges);
|
||||
|
||||
// There always seems to be one or more root nodes each with single edge and we want to have them static on the
|
||||
// left neatly in something like grid layout
|
||||
[...roots, ...secondLevelRoots].forEach((n, index) => {
|
||||
n.fx = n.x;
|
||||
});
|
||||
|
||||
const simulation = forceSimulation(nodes)
|
||||
.force(
|
||||
'link',
|
||||
forceLink(edges)
|
||||
.id((d) => d.id)
|
||||
.distance(config.linkDistance)
|
||||
.strength(config.linkStrength)
|
||||
)
|
||||
// to keep the left to right layout we add force that pulls all nodes to right but because roots are fixed it will
|
||||
// apply only to non root nodes
|
||||
.force('x', forceX(config.forceX).strength(config.forceXStrength))
|
||||
// Make sure nodes don't overlap
|
||||
.force('collide', forceCollide(config.forceCollide));
|
||||
|
||||
// 300 ticks for the simulation are recommended but less would probably work too, most movement is done in first
|
||||
// few iterations and then all the forces gets smaller https://github.com/d3/d3-force#simulation_alphaDecay
|
||||
simulation.tick(config.tick);
|
||||
simulation.stop();
|
||||
|
||||
// We do centering here instead of using centering force to keep this more stable
|
||||
centerNodes(nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* This initializes positions of the graph by going from the root to its children and laying it out in a grid from left
|
||||
* to right. This works only so, so because service map graphs can have cycles and children levels are not ordered in a
|
||||
* way to minimize the edge lengths. Nevertheless this seems to make the graph easier to nudge with the forces later on
|
||||
* than with the d3 default initial positioning. Also we can fix the root positions later on for a bit more neat
|
||||
* organisation.
|
||||
*
|
||||
* This function directly modifies the nodes given and only returns references to root nodes so they do not have to be
|
||||
* found again later on.
|
||||
*
|
||||
* How the spacing could look like approximately:
|
||||
* 0 - 0 - 0 - 0
|
||||
* \- 0 - 0 |
|
||||
* \- 0 -/
|
||||
* 0 - 0 -/
|
||||
*/
|
||||
function initializePositions(nodes, edges) {
|
||||
// To prevent going in cycles
|
||||
const alreadyPositioned = {};
|
||||
|
||||
const nodesMap = nodes.reduce((acc, node) => {
|
||||
acc[node.id] = node;
|
||||
return acc;
|
||||
}, {});
|
||||
const edgesMap = edges.reduce((acc, edge) => {
|
||||
const sourceId = edge.source;
|
||||
acc[sourceId] = [...(acc[sourceId] || []), edge];
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
let roots = nodes.filter((n) => n.incoming === 0);
|
||||
|
||||
// For things like service maps we assume there is some root (client) node but if there is none then selecting
|
||||
// any node as a starting point should work the same.
|
||||
if (!roots.length) {
|
||||
roots = [nodes[0]];
|
||||
}
|
||||
|
||||
let secondLevelRoots = roots.reduce((acc, r) => {
|
||||
acc.push(...(edgesMap[r.id] ? edgesMap[r.id].map((e) => nodesMap[e.target]) : []));
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const rootYSpacing = 300;
|
||||
const nodeYSpacing = 200;
|
||||
const nodeXSpacing = 200;
|
||||
|
||||
let rootY = 0;
|
||||
for (const root of roots) {
|
||||
let graphLevel = [root];
|
||||
let x = 0;
|
||||
while (graphLevel.length > 0) {
|
||||
const nextGraphLevel = [];
|
||||
let y = rootY;
|
||||
for (const node of graphLevel) {
|
||||
if (alreadyPositioned[node.id]) {
|
||||
continue;
|
||||
}
|
||||
// Initialize positions based on the spacing in the grid
|
||||
node.x = x;
|
||||
node.y = y;
|
||||
alreadyPositioned[node.id] = true;
|
||||
|
||||
// Move to next Y position for next node
|
||||
y += nodeYSpacing;
|
||||
if (edgesMap[node.id]) {
|
||||
nextGraphLevel.push(...edgesMap[node.id].map((edge) => nodesMap[edge.target]));
|
||||
}
|
||||
}
|
||||
|
||||
graphLevel = nextGraphLevel;
|
||||
// Move to next X position for next level
|
||||
x += nodeXSpacing;
|
||||
// Reset Y back to baseline for this root
|
||||
y = rootY;
|
||||
}
|
||||
rootY += rootYSpacing;
|
||||
}
|
||||
return { roots, secondLevelRoots };
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the center of the graph based on its bound is in 0, 0 coordinates.
|
||||
* Modifies the nodes directly.
|
||||
*/
|
||||
function centerNodes(nodes) {
|
||||
const bounds = graphBounds(nodes);
|
||||
for (let node of nodes) {
|
||||
node.x = node.x - bounds.center.x;
|
||||
node.y = node.y - bounds.center.y;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bounds of the graph meaning the extent of the nodes in all directions.
|
||||
*/
|
||||
function graphBounds(nodes) {
|
||||
if (nodes.length === 0) {
|
||||
return { top: 0, right: 0, bottom: 0, left: 0, center: { x: 0, y: 0 } };
|
||||
}
|
||||
|
||||
const bounds = nodes.reduce(
|
||||
(acc, node) => {
|
||||
if (node.x > acc.right) {
|
||||
acc.right = node.x;
|
||||
}
|
||||
if (node.x < acc.left) {
|
||||
acc.left = node.x;
|
||||
}
|
||||
if (node.y > acc.bottom) {
|
||||
acc.bottom = node.y;
|
||||
}
|
||||
if (node.y < acc.top) {
|
||||
acc.top = node.y;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ top: Infinity, right: -Infinity, bottom: -Infinity, left: Infinity }
|
||||
);
|
||||
|
||||
const y = bounds.top + (bounds.bottom - bounds.top) / 2;
|
||||
const x = bounds.left + (bounds.right - bounds.left) / 2;
|
||||
|
||||
return {
|
||||
...bounds,
|
||||
center: {
|
||||
x,
|
||||
y,
|
||||
},
|
||||
};
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { CorsWorker as Worker } from 'app/core/utils/CorsWorker';
|
||||
|
||||
export default function loadKusto() {
|
||||
return new Promise<void>((resolve) =>
|
||||
__non_webpack_require__(['vs/language/kusto/monaco.contribution'], () => resolve())
|
||||
);
|
||||
return new Worker(new URL('@kusto/monaco-kusto/release/esm/kusto.worker', import.meta.url));
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
export const monaco = 'monaco';
|
@ -1,7 +1,7 @@
|
||||
import { Config } from 'app/plugins/panel/nodeGraph/layout';
|
||||
import { EdgeDatum, NodeDatum } from 'app/plugins/panel/nodeGraph/types';
|
||||
|
||||
const { layout } = jest.requireActual('../../app/plugins/panel/nodeGraph/layout.worker.js');
|
||||
const { layout } = jest.requireActual('../../app/plugins/panel/nodeGraph/layout.worker.utils.js');
|
||||
|
||||
class LayoutMockWorker {
|
||||
timeout: number | undefined;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import { configure } from '@testing-library/react';
|
||||
import i18next from 'i18next';
|
||||
import failOnConsole from 'jest-fail-on-console';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
@ -20,3 +21,7 @@ i18next.use(initReactI18next).init({
|
||||
returnEmptyString: false,
|
||||
lng: 'en-US', // this should be the locale of the phrases in our source JSX
|
||||
});
|
||||
|
||||
// our tests are heavy in CI due to parallelisation and monaco and kusto
|
||||
// so we increase the default timeout to 2secs to avoid flakiness
|
||||
configure({ asyncUtilTimeout: 2000 });
|
||||
|
@ -1,4 +1,3 @@
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
|
||||
@ -52,7 +51,13 @@ module.exports = {
|
||||
string_decoder: false,
|
||||
},
|
||||
},
|
||||
ignoreWarnings: [/export .* was not found in/],
|
||||
ignoreWarnings: [
|
||||
/export .* was not found in/,
|
||||
{
|
||||
module: /@kusto\/language-service\/bridge\.min\.js$/,
|
||||
message: /^Critical dependency: the request of a dependency is an expression$/,
|
||||
},
|
||||
],
|
||||
stats: {
|
||||
children: false,
|
||||
source: false,
|
||||
@ -65,25 +70,6 @@ module.exports = {
|
||||
new webpack.ProvidePlugin({
|
||||
Buffer: ['buffer', 'Buffer'],
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
context: path.join(require.resolve('monaco-editor/package.json'), '../min/vs/'),
|
||||
from: '**/*',
|
||||
to: '../lib/monaco/min/vs/', // inside the public/build folder
|
||||
globOptions: {
|
||||
ignore: [
|
||||
'**/*.map', // debug files
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
context: path.join(require.resolve('@kusto/monaco-kusto/package.json'), '../release/min'),
|
||||
from: '**/*',
|
||||
to: '../lib/monaco/min/vs/language/kusto/',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
|
465
yarn.lock
465
yarn.lock
@ -399,6 +399,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/parser@npm:^7.22.15":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/parser@npm:7.23.6"
|
||||
bin:
|
||||
parser: ./bin/babel-parser.js
|
||||
checksum: 10/6be3a63d3c9d07b035b5a79c022327cb7e16cbd530140ecb731f19a650c794c315a72c699a22413ebeafaff14aa8f53435111898d59e01a393d741b85629fa7d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.22.15, @babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.23.3":
|
||||
version: 7.23.3
|
||||
resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.23.3"
|
||||
@ -1679,7 +1688,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/template@npm:^7.22.15, @babel/template@npm:^7.22.5, @babel/template@npm:^7.23.9, @babel/template@npm:^7.3.3":
|
||||
"@babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3":
|
||||
version: 7.22.15
|
||||
resolution: "@babel/template@npm:7.22.15"
|
||||
dependencies:
|
||||
"@babel/code-frame": "npm:^7.22.13"
|
||||
"@babel/parser": "npm:^7.22.15"
|
||||
"@babel/types": "npm:^7.22.15"
|
||||
checksum: 10/21e768e4eed4d1da2ce5d30aa51db0f4d6d8700bc1821fec6292587df7bba2fe1a96451230de8c64b989740731888ebf1141138bfffb14cacccf4d05c66ad93f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/template@npm:^7.22.5, @babel/template@npm:^7.23.9":
|
||||
version: 7.23.9
|
||||
resolution: "@babel/template@npm:7.23.9"
|
||||
dependencies:
|
||||
@ -1708,7 +1728,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
|
||||
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.2.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.6, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3":
|
||||
version: 7.23.6
|
||||
resolution: "@babel/types@npm:7.23.6"
|
||||
dependencies:
|
||||
"@babel/helper-string-parser": "npm:^7.23.4"
|
||||
"@babel/helper-validator-identifier": "npm:^7.22.20"
|
||||
to-fast-properties: "npm:^2.0.0"
|
||||
checksum: 10/07e70bb94d30b0231396b5e9a7726e6d9227a0a62e0a6830c0bd3232f33b024092e3d5a7d1b096a65bbf2bb43a9ab4c721bf618e115bfbb87b454fa060f88cbf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/types@npm:^7.23.9":
|
||||
version: 7.23.9
|
||||
resolution: "@babel/types@npm:7.23.9"
|
||||
dependencies:
|
||||
@ -3749,17 +3780,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grafana/faro-core@npm:^1.3.6, @grafana/faro-core@npm:^1.3.7":
|
||||
version: 1.3.7
|
||||
resolution: "@grafana/faro-core@npm:1.3.7"
|
||||
dependencies:
|
||||
"@opentelemetry/api": "npm:^1.7.0"
|
||||
"@opentelemetry/otlp-transformer": "npm:^0.45.1"
|
||||
checksum: 10/fa3ff8dce1e6fe5ad91a4d42bb9bdb13f36d594074566a100645ffb4bc509265d18c78c5cda1ef8f39a3f043c1901baee620d3e044b3a0a6e9d1c516bf71f74f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grafana/faro-core@npm:^1.3.8":
|
||||
"@grafana/faro-core@npm:^1.3.6, @grafana/faro-core@npm:^1.3.8":
|
||||
version: 1.3.8
|
||||
resolution: "@grafana/faro-core@npm:1.3.8"
|
||||
dependencies:
|
||||
@ -3769,6 +3790,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grafana/faro-core@npm:^1.3.7":
|
||||
version: 1.3.7
|
||||
resolution: "@grafana/faro-core@npm:1.3.7"
|
||||
dependencies:
|
||||
"@opentelemetry/api": "npm:^1.7.0"
|
||||
"@opentelemetry/otlp-transformer": "npm:^0.45.1"
|
||||
checksum: 10/fa3ff8dce1e6fe5ad91a4d42bb9bdb13f36d594074566a100645ffb4bc509265d18c78c5cda1ef8f39a3f043c1901baee620d3e044b3a0a6e9d1c516bf71f74f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@grafana/faro-web-sdk@npm:1.3.8":
|
||||
version: 1.3.8
|
||||
resolution: "@grafana/faro-web-sdk@npm:1.3.8"
|
||||
@ -4737,6 +4768,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/resolve-uri@npm:3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "@jridgewell/resolve-uri@npm:3.1.0"
|
||||
checksum: 10/320ceb37af56953757b28e5b90c34556157676d41e3d0a3ff88769274d62373582bb0f0276a4f2d29c3f4fdd55b82b8be5731f52d391ad2ecae9b321ee1c742d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0":
|
||||
version: 3.1.1
|
||||
resolution: "@jridgewell/resolve-uri@npm:3.1.1"
|
||||
@ -4751,6 +4789,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/source-map@npm:^0.3.2":
|
||||
version: 0.3.2
|
||||
resolution: "@jridgewell/source-map@npm:0.3.2"
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping": "npm:^0.3.0"
|
||||
"@jridgewell/trace-mapping": "npm:^0.3.9"
|
||||
checksum: 10/1aaa42075bac32a551708025da0c07b11c11fb05ccd10fb70df2cb0db88773338ab0f33f175d9865379cb855bb3b1cda478367747a1087309fda40a7b9214bfa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/source-map@npm:^0.3.3":
|
||||
version: 0.3.5
|
||||
resolution: "@jridgewell/source-map@npm:0.3.5"
|
||||
@ -4761,6 +4809,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/sourcemap-codec@npm:1.4.14":
|
||||
version: 1.4.14
|
||||
resolution: "@jridgewell/sourcemap-codec@npm:1.4.14"
|
||||
checksum: 10/26e768fae6045481a983e48aa23d8fcd23af5da70ebd74b0649000e815e7fbb01ea2bc088c9176b3fffeb9bec02184e58f46125ef3320b30eaa1f4094cfefa38
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15":
|
||||
version: 1.4.15
|
||||
resolution: "@jridgewell/sourcemap-codec@npm:1.4.15"
|
||||
@ -4778,7 +4833,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.21, @jridgewell/trace-mapping@npm:^0.3.9":
|
||||
"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.18, @jridgewell/trace-mapping@npm:^0.3.9":
|
||||
version: 0.3.18
|
||||
resolution: "@jridgewell/trace-mapping@npm:0.3.18"
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri": "npm:3.1.0"
|
||||
"@jridgewell/sourcemap-codec": "npm:1.4.14"
|
||||
checksum: 10/f4fabdddf82398a797bcdbb51c574cd69b383db041a6cae1a6a91478681d6aab340c01af655cfd8c6e01cde97f63436a1445f08297cdd33587621cf05ffa0d55
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/trace-mapping@npm:^0.3.20":
|
||||
version: 0.3.21
|
||||
resolution: "@jridgewell/trace-mapping@npm:0.3.21"
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri": "npm:^3.1.0"
|
||||
"@jridgewell/sourcemap-codec": "npm:^1.4.14"
|
||||
checksum: 10/925dda0620887e5a24f11b5a3a106f4e8b1a66155b49be6ceee61432174df33a17c243d8a89b2cd79ccebd281d817878759236a2fc42c47325ae9f73dfbfb90d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@jridgewell/trace-mapping@npm:^0.3.21":
|
||||
version: 0.3.22
|
||||
resolution: "@jridgewell/trace-mapping@npm:0.3.22"
|
||||
dependencies:
|
||||
@ -7096,13 +7171,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@remix-run/router@npm:1.14.2, @remix-run/router@npm:^1.5.0":
|
||||
"@remix-run/router@npm:1.14.2":
|
||||
version: 1.14.2
|
||||
resolution: "@remix-run/router@npm:1.14.2"
|
||||
checksum: 10/422844e88b985f1e287301b302c6cf8169c9eea792f80d40464f97b25393bb2e697228ebd7a7b61444d5a51c5873c4a637aad20acde5886a5caf62e833c5ceee
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@remix-run/router@npm:^1.5.0":
|
||||
version: 1.11.0
|
||||
resolution: "@remix-run/router@npm:1.11.0"
|
||||
checksum: 10/629ec578b9dfd3c5cb5de64a0798dd7846ec5ba0351aa66f42b1c65efb43da8f30366be59b825303648965b0df55b638c110949b24ef94fd62e98117fdfb0c0f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@rollup/plugin-commonjs@npm:25.0.7":
|
||||
version: 25.0.7
|
||||
resolution: "@rollup/plugin-commonjs@npm:25.0.7"
|
||||
@ -8410,6 +8492,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-darwin-arm64@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-darwin-arm64@npm:1.3.90"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-darwin-arm64@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-darwin-arm64@npm:1.4.0"
|
||||
@ -8424,6 +8513,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-darwin-x64@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-darwin-x64@npm:1.3.90"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-darwin-x64@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-darwin-x64@npm:1.4.0"
|
||||
@ -8438,6 +8534,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.90"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-arm-gnueabihf@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.4.0"
|
||||
@ -8452,6 +8555,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-arm64-gnu@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-linux-arm64-gnu@npm:1.3.90"
|
||||
conditions: os=linux & cpu=arm64 & libc=glibc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-arm64-gnu@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-linux-arm64-gnu@npm:1.4.0"
|
||||
@ -8466,6 +8576,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-arm64-musl@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-linux-arm64-musl@npm:1.3.90"
|
||||
conditions: os=linux & cpu=arm64 & libc=musl
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-arm64-musl@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-linux-arm64-musl@npm:1.4.0"
|
||||
@ -8480,6 +8597,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-x64-gnu@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-linux-x64-gnu@npm:1.3.90"
|
||||
conditions: os=linux & cpu=x64 & libc=glibc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-x64-gnu@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-linux-x64-gnu@npm:1.4.0"
|
||||
@ -8494,6 +8618,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-x64-musl@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-linux-x64-musl@npm:1.3.90"
|
||||
conditions: os=linux & cpu=x64 & libc=musl
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-linux-x64-musl@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-linux-x64-musl@npm:1.4.0"
|
||||
@ -8508,6 +8639,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-win32-arm64-msvc@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-win32-arm64-msvc@npm:1.3.90"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-win32-arm64-msvc@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-win32-arm64-msvc@npm:1.4.0"
|
||||
@ -8522,6 +8660,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-win32-ia32-msvc@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-win32-ia32-msvc@npm:1.3.90"
|
||||
conditions: os=win32 & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-win32-ia32-msvc@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-win32-ia32-msvc@npm:1.4.0"
|
||||
@ -8536,6 +8681,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-win32-x64-msvc@npm:1.3.90":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core-win32-x64-msvc@npm:1.3.90"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core-win32-x64-msvc@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core-win32-x64-msvc@npm:1.4.0"
|
||||
@ -8550,7 +8702,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core@npm:1.4.0, @swc/core@npm:^1.3.49":
|
||||
"@swc/core@npm:1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "@swc/core@npm:1.4.0"
|
||||
dependencies:
|
||||
@ -8642,6 +8794,52 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/core@npm:^1.3.49":
|
||||
version: 1.3.90
|
||||
resolution: "@swc/core@npm:1.3.90"
|
||||
dependencies:
|
||||
"@swc/core-darwin-arm64": "npm:1.3.90"
|
||||
"@swc/core-darwin-x64": "npm:1.3.90"
|
||||
"@swc/core-linux-arm-gnueabihf": "npm:1.3.90"
|
||||
"@swc/core-linux-arm64-gnu": "npm:1.3.90"
|
||||
"@swc/core-linux-arm64-musl": "npm:1.3.90"
|
||||
"@swc/core-linux-x64-gnu": "npm:1.3.90"
|
||||
"@swc/core-linux-x64-musl": "npm:1.3.90"
|
||||
"@swc/core-win32-arm64-msvc": "npm:1.3.90"
|
||||
"@swc/core-win32-ia32-msvc": "npm:1.3.90"
|
||||
"@swc/core-win32-x64-msvc": "npm:1.3.90"
|
||||
"@swc/counter": "npm:^0.1.1"
|
||||
"@swc/types": "npm:^0.1.5"
|
||||
peerDependencies:
|
||||
"@swc/helpers": ^0.5.0
|
||||
dependenciesMeta:
|
||||
"@swc/core-darwin-arm64":
|
||||
optional: true
|
||||
"@swc/core-darwin-x64":
|
||||
optional: true
|
||||
"@swc/core-linux-arm-gnueabihf":
|
||||
optional: true
|
||||
"@swc/core-linux-arm64-gnu":
|
||||
optional: true
|
||||
"@swc/core-linux-arm64-musl":
|
||||
optional: true
|
||||
"@swc/core-linux-x64-gnu":
|
||||
optional: true
|
||||
"@swc/core-linux-x64-musl":
|
||||
optional: true
|
||||
"@swc/core-win32-arm64-msvc":
|
||||
optional: true
|
||||
"@swc/core-win32-ia32-msvc":
|
||||
optional: true
|
||||
"@swc/core-win32-x64-msvc":
|
||||
optional: true
|
||||
peerDependenciesMeta:
|
||||
"@swc/helpers":
|
||||
optional: true
|
||||
checksum: 10/214af37af77b968203d495745a86db985734527f4696243bda5fb9ce868830d70e7a2cdbb268da2ee994d9fcedded25073d7b709fa09b75e96f9ba7d13a63da0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/counter@npm:^0.1.1, @swc/counter@npm:^0.1.2, @swc/counter@npm:^0.1.3":
|
||||
version: 0.1.3
|
||||
resolution: "@swc/counter@npm:0.1.3"
|
||||
@ -8649,7 +8847,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/helpers@npm:0.5.6, @swc/helpers@npm:^0.5.0":
|
||||
"@swc/helpers@npm:0.5.6":
|
||||
version: 0.5.6
|
||||
resolution: "@swc/helpers@npm:0.5.6"
|
||||
dependencies:
|
||||
@ -8658,6 +8856,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/helpers@npm:^0.5.0":
|
||||
version: 0.5.1
|
||||
resolution: "@swc/helpers@npm:0.5.1"
|
||||
dependencies:
|
||||
tslib: "npm:^2.4.0"
|
||||
checksum: 10/4954c4d2dd97bf965e863a10ffa44c3fdaf7653f2fa9ef1a6cf7ffffd67f3f832216588f9751afd75fdeaea60c4688c75c01e2405119c448f1a109c9a7958c54
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@swc/types@npm:^0.1.5":
|
||||
version: 0.1.5
|
||||
resolution: "@swc/types@npm:0.1.5"
|
||||
@ -8681,7 +8888,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@testing-library/jest-dom@npm:6.4.2, @testing-library/jest-dom@npm:^6.1.2":
|
||||
"@testing-library/jest-dom@npm:6.4.2":
|
||||
version: 6.4.2
|
||||
resolution: "@testing-library/jest-dom@npm:6.4.2"
|
||||
dependencies:
|
||||
@ -8714,6 +8921,39 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@testing-library/jest-dom@npm:^6.1.2":
|
||||
version: 6.2.1
|
||||
resolution: "@testing-library/jest-dom@npm:6.2.1"
|
||||
dependencies:
|
||||
"@adobe/css-tools": "npm:^4.3.2"
|
||||
"@babel/runtime": "npm:^7.9.2"
|
||||
aria-query: "npm:^5.0.0"
|
||||
chalk: "npm:^3.0.0"
|
||||
css.escape: "npm:^1.5.1"
|
||||
dom-accessibility-api: "npm:^0.6.3"
|
||||
lodash: "npm:^4.17.15"
|
||||
redent: "npm:^3.0.0"
|
||||
peerDependencies:
|
||||
"@jest/globals": ">= 28"
|
||||
"@types/bun": "*"
|
||||
"@types/jest": ">= 28"
|
||||
jest: ">= 28"
|
||||
vitest: ">= 0.32"
|
||||
peerDependenciesMeta:
|
||||
"@jest/globals":
|
||||
optional: true
|
||||
"@types/bun":
|
||||
optional: true
|
||||
"@types/jest":
|
||||
optional: true
|
||||
jest:
|
||||
optional: true
|
||||
vitest:
|
||||
optional: true
|
||||
checksum: 10/e522314c4623d2030146570ed5907c71126477272760fa6bce7a2db4ee5dd1edf492ebc9a5f442e99f69d4d6e2a9d0aac49fae41323211dbcee186a1eca04707
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@testing-library/react-hooks@npm:^8.0.1":
|
||||
version: 8.0.1
|
||||
resolution: "@testing-library/react-hooks@npm:8.0.1"
|
||||
@ -9800,7 +10040,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:20.11.19, @types/node@npm:^20.11.16":
|
||||
"@types/node@npm:20.11.19":
|
||||
version: 20.11.19
|
||||
resolution: "@types/node@npm:20.11.19"
|
||||
dependencies:
|
||||
@ -9823,6 +10063,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^20.11.16":
|
||||
version: 20.11.18
|
||||
resolution: "@types/node@npm:20.11.18"
|
||||
dependencies:
|
||||
undici-types: "npm:~5.26.4"
|
||||
checksum: 10/eeaa55032e6702867e96d7b6f98df1d60af09d37ab72f2b905b349ec7e458dfb9c4d9cfc562962f5a51b156a968eea773d8025688f88b735944c81e3ac0e3b7f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/normalize-package-data@npm:^2.4.0":
|
||||
version: 2.4.1
|
||||
resolution: "@types/normalize-package-data@npm:2.4.1"
|
||||
@ -9939,7 +10188,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-dom@npm:*, @types/react-dom@npm:18.2.19, @types/react-dom@npm:^18.0.0":
|
||||
"@types/react-dom@npm:*, @types/react-dom@npm:^18.0.0":
|
||||
version: 18.2.7
|
||||
resolution: "@types/react-dom@npm:18.2.7"
|
||||
dependencies:
|
||||
"@types/react": "npm:*"
|
||||
checksum: 10/9b70ef66cbe2d2898ea37eb79ee3697e0e4ad3d950e769a601f79be94097d43b8ef45b98a0b29528203c7d731c81666f637b2b7032deeced99214b4bc0662614
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-dom@npm:18.2.19":
|
||||
version: 18.2.19
|
||||
resolution: "@types/react-dom@npm:18.2.19"
|
||||
dependencies:
|
||||
@ -11386,6 +11644,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"acorn@npm:^8.5.0":
|
||||
version: 8.10.0
|
||||
resolution: "acorn@npm:8.10.0"
|
||||
bin:
|
||||
acorn: bin/acorn
|
||||
checksum: 10/522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"add-dom-event-listener@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "add-dom-event-listener@npm:1.1.0"
|
||||
@ -12080,13 +12347,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axe-core@npm:=4.7.0, axe-core@npm:^4.2.0":
|
||||
"axe-core@npm:=4.7.0":
|
||||
version: 4.7.0
|
||||
resolution: "axe-core@npm:4.7.0"
|
||||
checksum: 10/615c0f7722c3c9fcf353dbd70b00e2ceae234d4c17cbc839dd85c01d16797c4e4da45f8d27c6118e9e6b033fb06efd196106e13651a1b2f3a10e0f11c7b2f660
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axe-core@npm:^4.2.0":
|
||||
version: 4.6.3
|
||||
resolution: "axe-core@npm:4.6.3"
|
||||
checksum: 10/280f6a7067129875380f733ae84093ce29c4b8cfe36e1a8ff46bd5d2bcd57d093f11b00223ddf5fef98ca147e0e6568ddd0ada9415cf8ae15d379224bf3cbb51
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axios@npm:^1.0.0":
|
||||
version: 1.5.1
|
||||
resolution: "axios@npm:1.5.1"
|
||||
@ -12651,7 +12925,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.21.10, browserslist@npm:^4.21.4, browserslist@npm:^4.22.2":
|
||||
"browserslist@npm:^4.0.0, browserslist@npm:^4.14.5, browserslist@npm:^4.21.4, browserslist@npm:^4.22.2":
|
||||
version: 4.22.2
|
||||
resolution: "browserslist@npm:4.22.2"
|
||||
dependencies:
|
||||
caniuse-lite: "npm:^1.0.30001565"
|
||||
electron-to-chromium: "npm:^1.4.601"
|
||||
node-releases: "npm:^2.0.14"
|
||||
update-browserslist-db: "npm:^1.0.13"
|
||||
bin:
|
||||
browserslist: cli.js
|
||||
checksum: 10/e3590793db7f66ad3a50817e7b7f195ce61e029bd7187200244db664bfbe0ac832f784e4f6b9c958aef8ea4abe001ae7880b7522682df521f4bc0a5b67660b5e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"browserslist@npm:^4.21.10":
|
||||
version: 4.22.3
|
||||
resolution: "browserslist@npm:4.22.3"
|
||||
dependencies:
|
||||
@ -12968,6 +13256,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"caniuse-lite@npm:^1.0.30001565":
|
||||
version: 1.0.30001579
|
||||
resolution: "caniuse-lite@npm:1.0.30001579"
|
||||
checksum: 10/2cd0c02e5d66b09888743ad2b624dbde697ace5c76b55bfd6065ea033f6abea8ac3f5d3c9299c042f91b396e2141b49bc61f5e17086dc9ba3a866cc6790134c0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"canvas-hypertxt@npm:^1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "canvas-hypertxt@npm:1.0.3"
|
||||
@ -13239,14 +13534,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cli-spinners@npm:2.6.1, cli-spinners@npm:^2.5.0":
|
||||
"cli-spinners@npm:2.6.1":
|
||||
version: 2.6.1
|
||||
resolution: "cli-spinners@npm:2.6.1"
|
||||
checksum: 10/3e2dc5df72cf02120bebe256881fc8e3ec49867e5023d39f1e7340d7da57964f5236f4c75e568aa9dea6460b56f7a6d5870b89453c743c6c15e213cb52be2122
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cli-spinners@npm:^2.9.2":
|
||||
"cli-spinners@npm:^2.5.0, cli-spinners@npm:^2.9.2":
|
||||
version: 2.9.2
|
||||
resolution: "cli-spinners@npm:2.9.2"
|
||||
checksum: 10/a0a863f442df35ed7294424f5491fa1756bd8d2e4ff0c8736531d886cec0ece4d85e8663b77a5afaf1d296e3cbbebff92e2e99f52bbea89b667cbe789b994794
|
||||
@ -14168,7 +14463,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"css-loader@npm:6.10.0, css-loader@npm:^6.7.1":
|
||||
"css-loader@npm:6.10.0":
|
||||
version: 6.10.0
|
||||
resolution: "css-loader@npm:6.10.0"
|
||||
dependencies:
|
||||
@ -14192,6 +14487,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"css-loader@npm:^6.7.1":
|
||||
version: 6.9.1
|
||||
resolution: "css-loader@npm:6.9.1"
|
||||
dependencies:
|
||||
icss-utils: "npm:^5.1.0"
|
||||
postcss: "npm:^8.4.33"
|
||||
postcss-modules-extract-imports: "npm:^3.0.0"
|
||||
postcss-modules-local-by-default: "npm:^4.0.4"
|
||||
postcss-modules-scope: "npm:^3.1.1"
|
||||
postcss-modules-values: "npm:^4.0.0"
|
||||
postcss-value-parser: "npm:^4.2.0"
|
||||
semver: "npm:^7.5.4"
|
||||
peerDependencies:
|
||||
webpack: ^5.0.0
|
||||
checksum: 10/6f897406188ed7f6db03daab0602ed86df1e967b48a048ab72d0ee223e59ab9e13c5235481b12deb79e12aadf0be43bc3bdee71e1dc1e875e4bcd91c05b464af
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"css-minimizer-webpack-plugin@npm:6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "css-minimizer-webpack-plugin@npm:6.0.0"
|
||||
@ -15696,6 +16009,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron-to-chromium@npm:^1.4.601":
|
||||
version: 1.4.625
|
||||
resolution: "electron-to-chromium@npm:1.4.625"
|
||||
checksum: 10/610a4eaabf6a064d8f6d4dfa25c55a3940f09a3b25edc8a271821d1b270bb28c4c9f19225d81bfc59deaa12c1f8f0144f3b4510631c6b6b47e0b6216737e216a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron-to-chromium@npm:^1.4.648":
|
||||
version: 1.4.648
|
||||
resolution: "electron-to-chromium@npm:1.4.648"
|
||||
@ -24128,14 +24448,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "outvariant@npm:1.4.0"
|
||||
checksum: 10/07b9bcb9b3a2ff1b3db02af6b07d70e663082b30ddc08ff475d7c85fc623fdcc4433a4ab5b88f6902b62dbb284eef1be386aa537e14cef0519fad887ec483054
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"outvariant@npm:^1.4.2":
|
||||
"outvariant@npm:^1.2.1, outvariant@npm:^1.4.0, outvariant@npm:^1.4.2":
|
||||
version: 1.4.2
|
||||
resolution: "outvariant@npm:1.4.2"
|
||||
checksum: 10/f16ba035fb65d1cbe7d2e06693dd42183c46bc8456713d9ddb5182d067defa7d78217edab0a2d3e173d3bacd627b2bd692195c7087c225b82548fbf52c677b38
|
||||
@ -25167,7 +25480,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4":
|
||||
"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4":
|
||||
version: 6.0.13
|
||||
resolution: "postcss-selector-parser@npm:6.0.13"
|
||||
dependencies:
|
||||
cssesc: "npm:^3.0.0"
|
||||
util-deprecate: "npm:^1.0.2"
|
||||
checksum: 10/e779aa1f8ca9ee45d562400aac6109a2bccc59559b6e15adec8bc2a71d395ca563a378fd68f6a61963b4ef2ca190e0c0486e6dc6c41d755f3b82dd6e480e6941
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"postcss-selector-parser@npm:^6.0.15":
|
||||
version: 6.0.15
|
||||
resolution: "postcss-selector-parser@npm:6.0.15"
|
||||
dependencies:
|
||||
@ -26841,7 +27164,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-use@npm:17.5.0, react-use@npm:^17.4.2":
|
||||
"react-use@npm:17.5.0":
|
||||
version: 17.5.0
|
||||
resolution: "react-use@npm:17.5.0"
|
||||
dependencies:
|
||||
@ -26866,6 +27189,31 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-use@npm:^17.4.2":
|
||||
version: 17.4.2
|
||||
resolution: "react-use@npm:17.4.2"
|
||||
dependencies:
|
||||
"@types/js-cookie": "npm:^2.2.6"
|
||||
"@xobotyi/scrollbar-width": "npm:^1.9.5"
|
||||
copy-to-clipboard: "npm:^3.3.1"
|
||||
fast-deep-equal: "npm:^3.1.3"
|
||||
fast-shallow-equal: "npm:^1.0.0"
|
||||
js-cookie: "npm:^2.2.1"
|
||||
nano-css: "npm:^5.6.1"
|
||||
react-universal-interface: "npm:^0.6.2"
|
||||
resize-observer-polyfill: "npm:^1.5.1"
|
||||
screenfull: "npm:^5.1.0"
|
||||
set-harmonic-interval: "npm:^1.0.1"
|
||||
throttle-debounce: "npm:^3.0.1"
|
||||
ts-easing: "npm:^0.2.0"
|
||||
tslib: "npm:^2.1.0"
|
||||
peerDependencies:
|
||||
react: "*"
|
||||
react-dom: "*"
|
||||
checksum: 10/56d2da474d949d22eb34ff3ffccf5526986d51ed68a8f4e64f4b79bdcff3f0ea55d322c104e3fc0819b08b8765e8eb3fa47d8b506e9d61ff1fdc7bd1374c17d6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-virtual@npm:2.10.4, react-virtual@npm:^2.8.2":
|
||||
version: 2.10.4
|
||||
resolution: "react-virtual@npm:2.10.4"
|
||||
@ -28260,14 +28608,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"signal-exit@npm:^4.0.1":
|
||||
version: 4.0.2
|
||||
resolution: "signal-exit@npm:4.0.2"
|
||||
checksum: 10/99d49eab7f24aeed79e44999500d5ff4b9fbb560b0e1f8d47096c54d625b995aeaec3032cce44527adf2de0c303731a8356e234a348d6801214a8a3385a1ff8e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"signal-exit@npm:^4.1.0":
|
||||
"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "signal-exit@npm:4.1.0"
|
||||
checksum: 10/c9fa63bbbd7431066174a48ba2dd9986dfd930c3a8b59de9c29d7b6854ec1c12a80d15310869ea5166d413b99f041bfa3dd80a7947bcd44ea8e6eb3ffeabfa1f
|
||||
@ -29695,7 +30036,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"terser-webpack-plugin@npm:5.3.10, terser-webpack-plugin@npm:^5.1.3, terser-webpack-plugin@npm:^5.3.1, terser-webpack-plugin@npm:^5.3.10, terser-webpack-plugin@npm:^5.3.7":
|
||||
"terser-webpack-plugin@npm:5.3.10, terser-webpack-plugin@npm:^5.3.10":
|
||||
version: 5.3.10
|
||||
resolution: "terser-webpack-plugin@npm:5.3.10"
|
||||
dependencies:
|
||||
@ -29717,6 +30058,28 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"terser-webpack-plugin@npm:^5.1.3, terser-webpack-plugin@npm:^5.3.1, terser-webpack-plugin@npm:^5.3.7":
|
||||
version: 5.3.9
|
||||
resolution: "terser-webpack-plugin@npm:5.3.9"
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping": "npm:^0.3.17"
|
||||
jest-worker: "npm:^27.4.5"
|
||||
schema-utils: "npm:^3.1.1"
|
||||
serialize-javascript: "npm:^6.0.1"
|
||||
terser: "npm:^5.16.8"
|
||||
peerDependencies:
|
||||
webpack: ^5.1.0
|
||||
peerDependenciesMeta:
|
||||
"@swc/core":
|
||||
optional: true
|
||||
esbuild:
|
||||
optional: true
|
||||
uglify-js:
|
||||
optional: true
|
||||
checksum: 10/339737a407e034b7a9d4a66e31d84d81c10433e41b8eae2ca776f0e47c2048879be482a9aa08e8c27565a2a949bc68f6e07f451bf4d9aa347dd61b3d000f5353
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"terser@npm:^5.0.0, terser@npm:^5.15.1, terser@npm:^5.26.0, terser@npm:^5.7.2":
|
||||
version: 5.27.0
|
||||
resolution: "terser@npm:5.27.0"
|
||||
@ -29731,6 +30094,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"terser@npm:^5.16.8":
|
||||
version: 5.17.2
|
||||
resolution: "terser@npm:5.17.2"
|
||||
dependencies:
|
||||
"@jridgewell/source-map": "npm:^0.3.2"
|
||||
acorn: "npm:^8.5.0"
|
||||
commander: "npm:^2.20.0"
|
||||
source-map-support: "npm:~0.5.20"
|
||||
bin:
|
||||
terser: bin/terser
|
||||
checksum: 10/6df529586a4913657547dd8bfe2b5a59704b7acbe4e49ac938a16f829a62226f98dafb19c88b7af66b245ea281ee5dbeec33a41349ac3c035855417b06ebd646
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"test-exclude@npm:^6.0.0":
|
||||
version: 6.0.0
|
||||
resolution: "test-exclude@npm:6.0.0"
|
||||
|
Loading…
Reference in New Issue
Block a user