Grafana UI: Expose unstable entrypoint (#97080)

* feat(grafana-ui): build unstable entrypoint for experimental components

* feat(plugins): expose grafana/ui/unstable

* build(grafana-ui): add rollup plugin to create alias package.json for unstable entrypoint

* build(packages): rewrite prepare npm script to generate alias packagejson files

* chore(packages): use relative paths in publishConfig for exports generation

* chore(frontend): move npmcli/package-json package to root package.json

* revert(grafana-ui): remove rollup plugin for generating alias package.json files

* chore(grafana-ui): clean up unstable directory postpack to prevent yarn lock issues

* build(packages): fix scope for pkgName usage

* feat(packages): create separate cjs and esm builds that validate with arethetypeswrong cli

* chore(yarn): refresh lock file

* fix(packages): make sure alias package.jsons point to existing files
pull/101546/head^2
Jack Westbrook 4 months ago committed by GitHub
parent 503bc2ba66
commit 859c12bbb4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      .github/CODEOWNERS
  2. 1
      .gitignore
  3. 1
      package.json
  4. 8
      packages/grafana-data/package.json
  5. 10
      packages/grafana-e2e-selectors/package.json
  6. 8
      packages/grafana-flamegraph/package.json
  7. 6
      packages/grafana-icons/package.json
  8. 8
      packages/grafana-prometheus/package.json
  9. 8
      packages/grafana-runtime/package.json
  10. 8
      packages/grafana-schema/package.json
  11. 12
      packages/grafana-ui/package.json
  12. 25
      packages/grafana-ui/rollup.config.ts
  13. 18
      packages/rollup.config.parts.ts
  14. 1
      public/app/features/plugins/loader/sharedDependencies.ts
  15. 84
      scripts/prepare-npm-package.js
  16. 21
      scripts/prepare-packagejson.js
  17. 14
      scripts/validate-npm-packages.sh
  18. 27
      yarn.lock

@ -620,7 +620,7 @@ playwright.config.ts @grafana/plugins-platform-frontend
/scripts/import_many_dashboards.sh @torkelo
/scripts/mixin-check.sh @bergquist
/scripts/openapi3/ @grafana/grafana-operator-experience-squad
/scripts/prepare-packagejson.js @grafana/frontend-ops
/scripts/prepare-npm-package.js @grafana/frontend-ops
/scripts/protobuf-check.sh @grafana/plugins-platform-backend
/scripts/stripnulls.sh @grafana/grafana-as-code
/scripts/tag_release.sh @grafana/grafana-developer-enablement-squad

1
.gitignore vendored

@ -148,6 +148,7 @@ pkg/services/quota/quotaimpl/storage/storage.json
# Ignoring frontend packages specifics
/packages/grafana-ui/.yarn/.cache
/packages/grafana-ui/.storybook/static
/packages/grafana-ui/unstable
/packages/**/dist
/packages/**/compiled
/packages/**/.rpt2_cache

@ -83,6 +83,7 @@
"@grafana/plugin-e2e": "1.17.1",
"@grafana/tsconfig": "^2.0.0",
"@manypkg/get-packages": "^2.2.0",
"@npmcli/package-json": "^5.2.0",
"@playwright/test": "1.50.1",
"@pmmmwh/react-refresh-webpack-plugin": "0.5.15",
"@react-types/button": "3.10.2",

@ -16,9 +16,9 @@
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.mjs",
"types": "./dist/cjs/index.d.cts",
"access": "public"
},
"files": [
@ -31,7 +31,7 @@
"build": "tsc -p ./tsconfig.build.json && rollup -c rollup.config.ts --configPlugin esbuild",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
"postpack": "mv package.json.bak package.json"
},
"dependencies": {

@ -19,9 +19,9 @@
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.mjs",
"types": "./dist/cjs/index.d.cts",
"access": "public"
},
"files": [
@ -35,7 +35,7 @@
"bundle": "rollup -c rollup.config.ts --configPlugin esbuild",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
"postpack": "mv package.json.bak package.json"
},
"devDependencies": {
@ -51,7 +51,7 @@
},
"dependencies": {
"@grafana/tsconfig": "^2.0.0",
"semver": "7.7.0",
"semver": "^7.7.0",
"tslib": "2.8.1",
"typescript": "5.7.3"
}

@ -19,9 +19,9 @@
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.mjs",
"types": "./dist/cjs/index.d.cts",
"access": "public"
},
"files": [
@ -35,7 +35,7 @@
"bundle": "rollup -c rollup.config.ts --configPlugin esbuild",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
"postpack": "mv package.json.bak package.json"
},
"browserslist": [

@ -15,9 +15,9 @@
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.mts",
"access": "public"
},
"files": [

@ -22,9 +22,9 @@
"./LICENSE_AGPL"
],
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.mjs",
"types": "./dist/cjs/index.d.cts",
"access": "public"
},
"scripts": {
@ -32,7 +32,7 @@
"bundle": "rollup -c rollup.config.ts --configPlugin esbuild",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
"postpack": "mv package.json.bak package.json"
},
"dependencies": {

@ -17,9 +17,9 @@
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.mjs",
"types": "./dist/cjs/index.d.cts",
"access": "public"
},
"files": [
@ -33,7 +33,7 @@
"bundle": "rollup -c rollup.config.ts --configPlugin esbuild",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
"postpack": "mv package.json.bak package.json"
},
"dependencies": {

@ -16,9 +16,9 @@
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.mjs",
"types": "./dist/cjs/index.d.cts",
"access": "public"
},
"files": [
@ -32,7 +32,7 @@
"bundle": "rollup -c rollup.config.ts --configPlugin esbuild",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-npm-package.js",
"postpack": "mv package.json.bak package.json"
},
"devDependencies": {

@ -19,9 +19,9 @@
"main": "src/index.ts",
"types": "src/index.ts",
"publishConfig": {
"main": "dist/index.js",
"module": "dist/esm/index.js",
"types": "dist/index.d.ts",
"main": "./dist/cjs/index.cjs",
"module": "./dist/esm/index.mjs",
"types": "./dist/cjs/index.d.cts",
"access": "public"
},
"files": [
@ -34,12 +34,12 @@
"scripts": {
"build": "tsc -p ./tsconfig.build.json && rollup -c rollup.config.ts --configPlugin esbuild",
"bundle": "rollup -c rollup.config.ts --configPlugin esbuild",
"clean": "rimraf ./dist ./compiled ./package.tgz",
"clean": "rimraf ./dist ./compiled ./unstable ./package.tgz",
"storybook": "storybook dev -p 9001 -c .storybook --no-open",
"storybook:build": "storybook build -o ./dist/storybook -c .storybook",
"typecheck": "tsc --emitDeclarationOnly false --noEmit",
"prepack": "cp package.json package.json.bak && node ../../scripts/prepare-packagejson.js",
"postpack": "mv package.json.bak package.json"
"prepack": "cp package.json package.json.bak && ALIAS_PACKAGE_NAME=unstable node ../../scripts/prepare-npm-package.js",
"postpack": "mv package.json.bak package.json && rimraf ./unstable"
},
"browserslist": [
"defaults",

@ -25,5 +25,30 @@ export default [
],
output: [cjsOutput(pkg), esmOutput(pkg, 'grafana-ui')],
},
{
input: 'src/unstable.ts',
plugins: [
...plugins,
svg({ stringify: true }),
copy({
targets: [{ src: iconSrcPaths, dest: './dist/public/' }],
flatten: false,
}),
],
output: [cjsOutput(pkg), esmOutput(pkg, 'grafana-ui')],
},
tsDeclarationOutput(pkg),
tsDeclarationOutput(pkg, {
input: './compiled/unstable.d.ts',
output: [
{
file: './dist/cjs/unstable.d.cts',
format: 'cjs',
},
{
file: './dist/esm/unstable.d.mts',
format: 'es',
},
],
}),
];

@ -1,6 +1,6 @@
// This file contains the common parts of the rollup configuration that are shared across multiple packages.
import nodeResolve from '@rollup/plugin-node-resolve';
import { dirname, resolve } from 'node:path';
import { dirname, join, resolve } from 'node:path';
import dts from 'rollup-plugin-dts';
import esbuild from 'rollup-plugin-esbuild';
import { nodeExternals } from 'rollup-plugin-node-externals';
@ -28,6 +28,7 @@ export function cjsOutput(pkg) {
format: 'cjs',
sourcemap: true,
dir: dirname(pkg.publishConfig.main),
entryFileNames: '[name].cjs',
esModule: true,
interop: 'compat',
};
@ -39,6 +40,7 @@ export function esmOutput(pkg, pkgName) {
format: 'esm',
sourcemap: true,
dir: dirname(pkg.publishConfig.module),
entryFileNames: '[name].mjs',
preserveModules: true,
preserveModulesRoot: resolve(projectCwd, `packages/${pkgName}/src`),
};
@ -49,10 +51,16 @@ export function tsDeclarationOutput(pkg, overrides = {}) {
return {
input: './compiled/index.d.ts',
plugins: [dts()],
output: {
file: pkg.publishConfig.types,
format: 'es',
},
output: [
{
file: pkg.publishConfig.types,
format: 'cjs',
},
{
file: join(dirname(pkg.publishConfig.module), 'index.d.mts'),
format: 'es',
},
],
...overrides,
};
}

@ -52,6 +52,7 @@ export const sharedDependenciesMap = {
'@grafana/runtime': grafanaRuntime,
'@grafana/slate-react': () => import('slate-react'),
'@grafana/ui': grafanaUI,
'@grafana/ui/unstable': () => import('@grafana/ui/src/unstable'),
'@kusto/monaco-kusto': () => import('@kusto/monaco-kusto'),
'app/core/app_events': {
default: appEvents,

@ -0,0 +1,84 @@
import PackageJson from '@npmcli/package-json';
import { mkdir } from 'node:fs/promises';
import { join, dirname } from 'node:path';
const cwd = process.cwd();
try {
const pkgJson = await PackageJson.load(cwd);
const cjsIndex = pkgJson.content.publishConfig?.main ?? pkgJson.content.main;
const esmIndex = pkgJson.content.publishConfig?.module ?? pkgJson.content.module;
const cjsTypes = pkgJson.content.publishConfig?.types ?? pkgJson.content.types;
const esmTypes = `./${join(dirname(esmIndex), 'index.d.mts')}`;
const exports = {
'./package.json': './package.json',
'.': {
import: {
types: esmTypes,
default: esmIndex,
},
require: {
types: cjsTypes,
default: cjsIndex,
},
},
};
pkgJson.update({
main: cjsIndex,
types: cjsTypes,
module: esmIndex,
exports,
});
await pkgJson.save();
// If an alias package name is provided we add an exports entry for the alias
// then generate an additional "nested" package.json for typescript resolution that
// doesn't use the exports property in package.json.
if (process.env.ALIAS_PACKAGE_NAME) {
const aliasName = process.env.ALIAS_PACKAGE_NAME;
pkgJson.update({
exports: {
...pkgJson.content.exports,
[`./${aliasName}`]: {
import: {
types: esmTypes.replace('index', aliasName),
default: esmIndex.replace('index', aliasName),
},
require: {
types: cjsTypes.replace('index', aliasName),
default: cjsTypes.replace('index', aliasName),
},
},
},
files: [...pkgJson.content.files, aliasName],
});
await pkgJson.save();
await createAliasPackageJsonFiles(pkgJson.content, aliasName);
}
} catch (e) {
console.error(e);
process.exit(1);
}
async function createAliasPackageJsonFiles(packageJsonContent, aliasName) {
const pkgName = `${packageJsonContent.name}/${aliasName}`;
try {
console.log(`📦 Writing alias package.json for ${pkgName}.`);
const pkgJsonPath = `${cwd}/${aliasName}`;
await mkdir(pkgJsonPath, { recursive: true });
const pkgJson = await PackageJson.create(pkgJsonPath, {
data: {
name: pkgName,
types: `../dist/cjs/${aliasName}.d.cts`,
main: `../dist/cjs/${aliasName}.cjs`,
module: `../dist/esm/${aliasName}.mjs`,
},
});
await pkgJson.save();
} catch (error) {
throw new Error(`Error generating package.json for ${pkgName}`, error);
}
}

@ -1,21 +0,0 @@
const fs = require('fs');
const cwd = process.cwd();
const packageJson = require(`${cwd}/package.json`);
const newPackageJson = {
...packageJson,
main: packageJson.publishConfig?.main ?? packageJson.main,
};
if (packageJson.publishConfig?.types) {
newPackageJson.types = packageJson.publishConfig.types;
}
if (packageJson.publishConfig?.module) {
newPackageJson.module = packageJson.publishConfig.module;
}
try {
fs.writeFileSync(`${cwd}/package.json`, JSON.stringify(newPackageJson, null, 2));
} catch (e) {}

@ -43,14 +43,14 @@ for file in "$ARTIFACTS_DIR"/*.tgz; do
fi
# Assert commonjs builds
if [ ! -d dist ] || [ ! -f dist/index.js ] || [ ! -f dist/index.d.ts ]; then
if [ ! -d dist ] || [ ! -f dist/cjs/index.cjs ] || [ ! -f dist/cjs/index.d.cts ]; then
echo -e "❌ Failed: Missing 'dist' directory or required commonjs files in package $dir_name.\n"
exit 1
fi
if [ "$(jq -r '.main' package.json)" != "dist/index.js" ] || \
[ "$(jq -r '.types' package.json)" != "dist/index.d.ts" ]; then
echo -e "❌ Failed: Incorrect package.json properties in package $dir_name.\n"
if [ "$(jq -r '.main' package.json)" != "./dist/cjs/index.cjs" ] || \
[ "$(jq -r '.types' package.json)" != "./dist/cjs/index.d.cts" ]; then
echo -e "❌ Failed: Incorrect cjs package.json properties in package $dir_name.\n"
exit 1
fi
@ -58,13 +58,13 @@ for file in "$ARTIFACTS_DIR"/*.tgz; do
esm_packages=("grafana-data" "grafana-ui" "grafana-runtime" "grafana-e2e-selectors" "grafana-schema")
for esm_package in "${esm_packages[@]}"; do
if [[ "$dir_name" == "$esm_package" ]]; then
if [ ! -d dist/esm ] || [ ! -f dist/esm/index.js ]; then
if [ ! -d dist/esm ] || [ ! -f dist/esm/index.mjs ]; then
echo -e "❌ Failed: Missing 'dist/esm' directory or required esm files in package $dir_name.\n"
exit 1
fi
if [ "$(jq -r '.module' package.json)" != "dist/esm/index.js" ]; then
echo -e "❌ Failed: Incorrect package.json properties in package $dir_name.\n"
if [ "$(jq -r '.module' package.json)" != "./dist/esm/index.mjs" ]; then
echo -e "❌ Failed: Incorrect esm package.json properties in package $dir_name.\n"
exit 1
fi
fi

@ -3110,7 +3110,7 @@ __metadata:
rollup-plugin-dts: "npm:^6.1.1"
rollup-plugin-esbuild: "npm:6.2.0"
rollup-plugin-node-externals: "npm:^8.0.0"
semver: "npm:7.7.0"
semver: "npm:^7.7.0"
tslib: "npm:2.8.1"
typescript: "npm:5.7.3"
languageName: unknown
@ -5444,6 +5444,21 @@ __metadata:
languageName: node
linkType: hard
"@npmcli/package-json@npm:^5.2.0":
version: 5.2.1
resolution: "@npmcli/package-json@npm:5.2.1"
dependencies:
"@npmcli/git": "npm:^5.0.0"
glob: "npm:^10.2.2"
hosted-git-info: "npm:^7.0.0"
json-parse-even-better-errors: "npm:^3.0.0"
normalize-package-data: "npm:^6.0.0"
proc-log: "npm:^4.0.0"
semver: "npm:^7.5.3"
checksum: 10/304a819b93f79a6e0e56cb371961a66d2db72142e310d545ecbbbe4d917025a30601aa8e63a5f0cc28f0fe281c116bdaf79b334619b105a1d027a2b769ecd137
languageName: node
linkType: hard
"@npmcli/promise-spawn@npm:^7.0.0":
version: 7.0.2
resolution: "@npmcli/promise-spawn@npm:7.0.2"
@ -18143,6 +18158,7 @@ __metadata:
"@manypkg/get-packages": "npm:^2.2.0"
"@msagl/core": "npm:^1.1.19"
"@msagl/parser": "npm:^1.1.19"
"@npmcli/package-json": "npm:^5.2.0"
"@opentelemetry/api": "npm:1.9.0"
"@opentelemetry/exporter-collector": "npm:0.25.0"
"@opentelemetry/semantic-conventions": "npm:1.28.0"
@ -28361,6 +28377,15 @@ __metadata:
languageName: node
linkType: hard
"semver@npm:^7.7.0":
version: 7.7.1
resolution: "semver@npm:7.7.1"
bin:
semver: bin/semver.js
checksum: 10/4cfa1eb91ef3751e20fc52e47a935a0118d56d6f15a837ab814da0c150778ba2ca4f1a4d9068b33070ea4273629e615066664c2cfcd7c272caf7a8a0f6518b2c
languageName: node
linkType: hard
"send@npm:0.19.0":
version: 0.19.0
resolution: "send@npm:0.19.0"

Loading…
Cancel
Save