mirror of https://github.com/grafana/grafana.git
				
				
				
			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)
This commit is contained in:
		
							parent
							
								
									b625d60aa9
								
							
						
					
					
						commit
						8f0ae76afe
					
				|  | @ -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"], | ||||
| } | ||||
|  |  | |||
							
								
								
									
										25
									
								
								yarn.lock
								
								
								
								
							
							
						
						
									
										25
									
								
								yarn.lock
								
								
								
								
							|  | @ -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…
	
		Reference in New Issue