Chore: Use yarn node-modules linker (#79947)

* Chore: Use yarn node-modules linker

* fix react-router types resolution

* temp skip failing tests

* remove yarn-links for internal path aliases to fix some webpack errors

* transpile all .ts files, even those in node_modules (usually our internal workspace packages

* fix transformers mock

* import react router type directly

* remove old resolution

* more cleanup

* remove preserveSymlinks: true from tsconfig to make Go To Definition resolve grafana ui to the original location

* developer guide

* update dev guide

* remove sdks

* reenable tests

* fix tsconfig trailing commas (where did they come from)
pull/81343/head^2
Josh Hunt 1 year ago committed by GitHub
parent b625d60aa9
commit 8f0ae76afe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 20
      .yarn/sdks/eslint/bin/eslint.js
  2. 20
      .yarn/sdks/eslint/lib/api.js
  3. 14
      .yarn/sdks/eslint/package.json
  4. 6
      .yarn/sdks/integrations.yml
  5. 7
      .yarn/sdks/prettier/package.json
  6. 20
      .yarn/sdks/typescript/bin/tsc
  7. 20
      .yarn/sdks/typescript/bin/tsserver
  8. 20
      .yarn/sdks/typescript/lib/tsc.js
  9. 225
      .yarn/sdks/typescript/lib/tsserver.js
  10. 225
      .yarn/sdks/typescript/lib/tsserverlibrary.js
  11. 20
      .yarn/sdks/typescript/lib/typescript.js
  12. 10
      .yarn/sdks/typescript/package.json
  13. 2
      .yarnrc.yml
  14. 19
      contribute/developer-guide.md
  15. 2
      jest.config.js
  16. 6
      package.json
  17. 19
      packages/grafana-data/src/transformations/transformers/filterByValue.test.ts
  18. 2
      public/app/core/navigation/types.ts
  19. 1
      scripts/webpack/webpack.dev.js
  20. 1
      scripts/webpack/webpack.prod.js
  21. 9
      tsconfig.json
  22. 25
      yarn.lock

@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint/bin/eslint.js
require(absPnpApiPath).setup();
}
}
// Defer to the real eslint/bin/eslint.js your application uses
module.exports = absRequire(`eslint/bin/eslint.js`);

@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint
require(absPnpApiPath).setup();
}
}
// Defer to the real eslint your application uses
module.exports = absRequire(`eslint`);

@ -1,14 +0,0 @@
{
"name": "eslint",
"version": "8.56.0-sdk",
"main": "./lib/api.js",
"type": "commonjs",
"bin": {
"eslint": "./bin/eslint.js"
},
"exports": {
"./package.json": "./package.json",
".": "./lib/api.js",
"./use-at-your-own-risk": "./lib/unsupported-api.js"
}
}

@ -1,6 +0,0 @@
# This file is automatically generated by @yarnpkg/sdks.
# Manual changes might be lost!
integrations:
- vscode
- vim

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

@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/bin/tsc
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/bin/tsc your application uses
module.exports = absRequire(`typescript/bin/tsc`);

@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/bin/tsserver
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/bin/tsserver your application uses
module.exports = absRequire(`typescript/bin/tsserver`);

@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsc.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsc.js your application uses
module.exports = absRequire(`typescript/lib/tsc.js`);

@ -1,225 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const moduleWrapper = tsserver => {
if (!process.versions.pnp) {
return tsserver;
}
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
// before forwarding it to TS, and to add it back on all returned paths.
function toEditorPath(str) {
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
// We also take the opportunity to turn virtual paths into physical ones;
// this makes it much easier to work with workspaces that list peer
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
// file instances instead of the real ones.
//
// We only do this to modules owned by the the dependency tree roots.
// This avoids breaking the resolution when jumping inside a vendor
// with peer dep (otherwise jumping into react-dom would show resolution
// errors on react).
//
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
str = normalize(str);
if (str.match(/\.zip\//)) {
switch (hostInfo) {
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
// VSCode only adds it automatically for supported schemes,
// so we have to do it manually for the `zip` scheme.
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
//
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
//
// 2021-10-08: VSCode changed the format in 1.61.
// Before | ^zip:/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
// 2022-04-06: VSCode changed the format in 1.66.
// Before | ^/zip//c:/foo/bar.zip/package.json
// After | ^/zip/c:/foo/bar.zip/package.json
//
// 2022-05-06: VSCode changed the format in 1.68
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default: {
str = `zip:${str}`;
} break;
}
} else {
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
}
}
return str;
}
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
// Force enable 'allowLocalPluginLoads'
// TypeScript tries to resolve plugins using a path relative to itself
// which doesn't work when using the global cache
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
// And here is the point where we hijack the VSCode <-> TS communications
// by adding ourselves in the middle. We locate everything that looks
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
parsedMessage != null &&
typeof parsedMessage === `object` &&
parsedMessage.arguments &&
typeof parsedMessage.arguments.hostInfo === `string`
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
hostInfo += ` <1.61`;
} else if (minor < 66) {
hostInfo += ` <1.66`;
} else if (minor < 68) {
hostInfo += ` <1.68`;
}
}
}
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;
};
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsserver.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsserver.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));

@ -1,225 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const moduleWrapper = tsserver => {
if (!process.versions.pnp) {
return tsserver;
}
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
// before forwarding it to TS, and to add it back on all returned paths.
function toEditorPath(str) {
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
// We also take the opportunity to turn virtual paths into physical ones;
// this makes it much easier to work with workspaces that list peer
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
// file instances instead of the real ones.
//
// We only do this to modules owned by the the dependency tree roots.
// This avoids breaking the resolution when jumping inside a vendor
// with peer dep (otherwise jumping into react-dom would show resolution
// errors on react).
//
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
str = normalize(str);
if (str.match(/\.zip\//)) {
switch (hostInfo) {
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
// VSCode only adds it automatically for supported schemes,
// so we have to do it manually for the `zip` scheme.
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
//
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
//
// 2021-10-08: VSCode changed the format in 1.61.
// Before | ^zip:/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
// 2022-04-06: VSCode changed the format in 1.66.
// Before | ^/zip//c:/foo/bar.zip/package.json
// After | ^/zip/c:/foo/bar.zip/package.json
//
// 2022-05-06: VSCode changed the format in 1.68
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default: {
str = `zip:${str}`;
} break;
}
} else {
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
}
}
return str;
}
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
// Force enable 'allowLocalPluginLoads'
// TypeScript tries to resolve plugins using a path relative to itself
// which doesn't work when using the global cache
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
// And here is the point where we hijack the VSCode <-> TS communications
// by adding ourselves in the middle. We locate everything that looks
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
parsedMessage != null &&
typeof parsedMessage === `object` &&
parsedMessage.arguments &&
typeof parsedMessage.arguments.hostInfo === `string`
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
hostInfo += ` <1.61`;
} else if (minor < 66) {
hostInfo += ` <1.66`;
} else if (minor < 68) {
hostInfo += ` <1.68`;
}
}
}
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;
};
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsserverlibrary.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));

@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript your application uses
module.exports = absRequire(`typescript`);

@ -1,10 +0,0 @@
{
"name": "typescript",
"version": "5.3.3-sdk",
"main": "./lib/typescript.js",
"type": "commonjs",
"bin": {
"tsc": "./bin/tsc",
"tsserver": "./bin/tsserver"
}
}

@ -4,7 +4,7 @@ enableGlobalCache: false
enableTelemetry: false
nodeLinker: pnp
nodeLinker: node-modules
packageExtensions:
'@storybook/core-common@7.4.5':

@ -8,8 +8,7 @@ Make sure you have the following dependencies installed before setting up your d
- [Git](https://git-scm.com/)
- [Go](https://golang.org/dl/) (see [go.mod](../go.mod#L3) for minimum required version)
- [Node.js (Long Term Support)](https://nodejs.org)
- [Yarn](https://yarnpkg.com)
- [Node.js (Long Term Support)](https://nodejs.org), with [corepack enabled](https://nodejs.org/api/corepack.html#enabling-the-feature)
### macOS
@ -19,7 +18,7 @@ We recommend using [Homebrew](https://brew.sh/) for installing any missing depen
brew install git
brew install go
brew install node@20
npm install -g yarn
corepack enable
```
### Windows
@ -37,14 +36,6 @@ For alternative ways of cloning the Grafana repository, please refer to [GitHub'
**Warning:** Do not use `go get` to download Grafana. Recent versions of Go have added behavior which isn't compatible with the way the Grafana repository is structured.
### Configure Editors
For some IDEs, additional configuration may be needed for Typescript to work with [Yarn plug'n'play](https://yarnpkg.com/features/pnp).
For [VSCode](https://yarnpkg.com/getting-started/editor-sdks#vscode) and [Vim](https://yarnpkg.com/getting-started/editor-sdks#vim),
it's as easy as running `yarn dlx @yarnpkg/sdks vscode` or `yarn dlx @yarnpkg/sdks vim`, respectively.
More information can be found [here](https://yarnpkg.com/getting-started/editor-sdks).
### Configure precommit hooks
We use pre-commit hooks (via [lefthook](https://github.com/evilmartians/lefthook)) to lint, fix, and format code as you commit your changes. Previously the Grafana repository automatically installed these hook when you did `yarn install`, but they are now opt in for all contributors
@ -259,6 +250,12 @@ The resulting image will be tagged as grafana/grafana:dev.
Are you having issues with setting up your environment? Here are some tips that might help.
### IDE configuration
Configure your IDE to use the Typescript version from the Grafana repository. The version should match the Typescript version in the package.json file, and is typically at the path `node_modules/.bin/tsc`.
Previously Grafana used Yarn PnP to install frontend dependencies, which required additional special IDE configuration. This is no longer the case. If you have custom paths in your IDE for ESLint, Prettier, or Typescript, you can now remove them and use the defaults from node_modules.
### Too many open files when running `make run`
Depending on your environment, you may have to increase the maximum number of open files allowed. For the rest of this section, we will assume you are on a Unix like OS (e.g. Linux/macOS), where you can control the maximum number of open files through the [ulimit](https://ss64.com/bash/ulimit.html) shell command.

@ -25,7 +25,7 @@ module.exports = {
transformIgnorePatterns: [
`/node_modules/(?!${esModules})`, // exclude es modules to prevent TS complaining
],
moduleDirectories: ['public'],
moduleDirectories: ['public', 'node_modules'],
roots: ['<rootDir>/public/app', '<rootDir>/public/test', '<rootDir>/packages'],
testRegex: '(\\.|/)(test)\\.(jsx?|tsx?)$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],

@ -121,6 +121,7 @@
"@types/react-dom": "18.2.18",
"@types/react-grid-layout": "1.3.5",
"@types/react-highlight-words": "0.16.7",
"@types/react-router": "5.1.20",
"@types/react-router-dom": "5.3.3",
"@types/react-table": "7.7.19",
"@types/react-test-renderer": "18.0.7",
@ -284,7 +285,6 @@
"angular-route": "1.8.3",
"angular-sanitize": "1.8.3",
"ansicolor": "1.1.100",
"app": "link:./public/app",
"baron": "3.0.3",
"brace": "0.11.1",
"calculate-size": "1.1.1",
@ -368,6 +368,7 @@
"react-redux": "8.1.3",
"react-resizable": "3.0.5",
"react-responsive-carousel": "^3.2.23",
"react-router": "5.3.3",
"react-router-dom": "5.3.3",
"react-router-dom-v5-compat": "^6.10.0",
"react-select": "5.8.0",
@ -385,21 +386,18 @@
"regenerator-runtime": "0.14.1",
"reselect": "4.1.8",
"rxjs": "7.8.1",
"sass": "link:./public/sass",
"selecto": "1.26.3",
"semver": "7.5.4",
"slate": "0.47.9",
"slate-plain-serializer": "0.7.13",
"slate-react": "0.22.10",
"symbol-observable": "4.0.0",
"test": "link:./public/test",
"tether-drop": "https://github.com/torkelo/drop",
"tinycolor2": "1.6.0",
"tslib": "2.6.2",
"tween-functions": "^1.2.0",
"uplot": "1.6.29",
"uuid": "9.0.1",
"vendor": "link:./public/vendor",
"visjs-network": "4.25.0",
"webpack-assets-manifest": "^5.1.0",
"whatwg-fetch": "3.6.20",

@ -12,18 +12,10 @@ import {
FilterByValueType,
} from './filterByValue';
import { DataTransformerID } from './ids';
import * as utils from './utils';
let transformationSupport = false;
jest.mock('./utils', () => {
const actual = jest.requireActual('./utils');
return {
...actual,
transformationsVariableSupport: () => {
return transformationSupport;
},
};
});
const mockTransformationsVariableSupport = jest.spyOn(utils, 'transformationsVariableSupport');
mockTransformationsVariableSupport.mockReturnValue(false);
const seriesAWithSingleField = toDataFrame({
name: 'A',
@ -122,7 +114,7 @@ describe('FilterByValue transformer', () => {
});
it('should interpolate dashboard variables', async () => {
transformationSupport = true;
mockTransformationsVariableSupport.mockReturnValue(true);
const lower: MatcherConfig<BasicValueMatcherOptions<string | number>> = {
id: ValueMatcherID.lower,
@ -164,10 +156,11 @@ describe('FilterByValue transformer', () => {
},
]);
});
transformationSupport = false;
});
it('should not interpolate dashboard variables when feature toggle is off', async () => {
mockTransformationsVariableSupport.mockReturnValue(false);
const lower: MatcherConfig<BasicValueMatcherOptions<number | string>> = {
id: ValueMatcherID.lower,
options: { value: 'notinterpolating' },

@ -1,5 +1,5 @@
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { RouteComponentProps } from 'react-router';
import { UrlQueryMap } from '@grafana/data';

@ -40,7 +40,6 @@ module.exports = (env = {}) => {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'esbuild-loader',
options: esbuildOptions,

@ -35,7 +35,6 @@ module.exports = (env = {}) =>
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'esbuild-loader',
options: esbuildOptions,

@ -10,10 +10,9 @@
"useUnknownInCatchVariables": true,
"incremental": true,
"tsBuildInfoFile": "./tsconfig.tsbuildinfo",
"preserveSymlinks": true,
"paths": {
"@grafana/schema/dist/esm/*": ["../packages/grafana-schema/src/*"]
}
"@grafana/schema/dist/esm/*": ["../packages/grafana-schema/src/*"],
},
},
"extends": "@grafana/tsconfig/base.json",
"include": [
@ -22,7 +21,7 @@
"public/test/**/*.ts",
"public/vendor/**/*.ts",
"packages/grafana-data/typings",
"packages/grafana-ui/src/types"
"packages/grafana-ui/src/types",
],
"exclude": ["public/app/**/webpack.config.ts"]
"exclude": ["public/app/**/webpack.config.ts"],
}

@ -9080,7 +9080,7 @@ __metadata:
languageName: node
linkType: hard
"@types/react-router@npm:*":
"@types/react-router@npm:*, @types/react-router@npm:5.1.20":
version: 5.1.20
resolution: "@types/react-router@npm:5.1.20"
dependencies:
@ -10702,12 +10702,6 @@ __metadata:
languageName: node
linkType: hard
"app@link:./public/app::locator=grafana%40workspace%3A.":
version: 0.0.0-use.local
resolution: "app@link:./public/app::locator=grafana%40workspace%3A."
languageName: node
linkType: soft
"append-buffer@npm:^1.0.2":
version: 1.0.2
resolution: "append-buffer@npm:1.0.2"
@ -17407,6 +17401,7 @@ __metadata:
"@types/react-grid-layout": "npm:1.3.5"
"@types/react-highlight-words": "npm:0.16.7"
"@types/react-resizable": "npm:3.0.7"
"@types/react-router": "npm:5.1.20"
"@types/react-router-dom": "npm:5.3.3"
"@types/react-table": "npm:7.7.19"
"@types/react-test-renderer": "npm:18.0.7"
@ -17441,7 +17436,6 @@ __metadata:
angular-route: "npm:1.8.3"
angular-sanitize: "npm:1.8.3"
ansicolor: "npm:1.1.100"
app: "link:./public/app"
autoprefixer: "npm:10.4.17"
baron: "npm:3.0.3"
blob-polyfill: "npm:7.0.20220408"
@ -17576,6 +17570,7 @@ __metadata:
react-refresh: "npm:0.14.0"
react-resizable: "npm:3.0.5"
react-responsive-carousel: "npm:^3.2.23"
react-router: "npm:5.3.3"
react-router-dom: "npm:5.3.3"
react-router-dom-v5-compat: "npm:^6.10.0"
react-select: "npm:5.8.0"
@ -17612,7 +17607,6 @@ __metadata:
stylelint-config-sass-guidelines: "npm:10.0.0"
symbol-observable: "npm:4.0.0"
terser-webpack-plugin: "npm:5.3.10"
test: "link:./public/test"
testing-library-selector: "npm:0.3.1"
tether-drop: "https://github.com/torkelo/drop"
tinycolor2: "npm:1.6.0"
@ -17624,7 +17618,6 @@ __metadata:
typescript: "npm:5.3.3"
uplot: "npm:1.6.29"
uuid: "npm:9.0.1"
vendor: "link:./public/vendor"
visjs-network: "npm:4.25.0"
webpack: "npm:5.90.0"
webpack-assets-manifest: "npm:^5.1.0"
@ -28519,12 +28512,6 @@ __metadata:
languageName: node
linkType: hard
"test@link:./public/test::locator=grafana%40workspace%3A.":
version: 0.0.0-use.local
resolution: "test@link:./public/test::locator=grafana%40workspace%3A."
languageName: node
linkType: soft
"testing-library-selector@npm:0.3.1":
version: 0.3.1
resolution: "testing-library-selector@npm:0.3.1"
@ -29844,12 +29831,6 @@ __metadata:
languageName: node
linkType: hard
"vendor@link:./public/vendor::locator=grafana%40workspace%3A.":
version: 0.0.0-use.local
resolution: "vendor@link:./public/vendor::locator=grafana%40workspace%3A."
languageName: node
linkType: soft
"verror@npm:1.10.0":
version: 1.10.0
resolution: "verror@npm:1.10.0"

Loading…
Cancel
Save