@grafana/create-plugin 6.8.0-canary.2356.20816081919.0 → 6.8.1-canary.2421.21476112829.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/codemods/additions/additions.js +3 -3
  3. package/dist/codemods/utils.js +2 -2
  4. package/package.json +3 -3
  5. package/src/codemods/additions/additions.ts +3 -3
  6. package/templates/backend/go.mod +30 -29
  7. package/templates/backend/go.sum +62 -62
  8. package/templates/backend-app/go.mod +30 -29
  9. package/templates/backend-app/go.sum +62 -62
  10. package/templates/common/.config/bundler/copyFiles.ts +23 -0
  11. package/templates/common/.config/docker-compose-base.yaml +1 -1
  12. package/templates/common/.config/rspack/BuildModeRspackPlugin.ts +4 -4
  13. package/templates/common/.config/rspack/{liveReloadPlugin.js → liveReloadPlugin.ts} +34 -11
  14. package/templates/common/.config/rspack/rspack.config.ts +8 -22
  15. package/templates/common/.config/webpack/BuildModeWebpackPlugin.ts +1 -1
  16. package/templates/common/.config/webpack/webpack.config.ts +4 -17
  17. package/templates/common/_package.json +46 -44
  18. package/templates/github/workflows/bundle-stats.yml +1 -1
  19. package/templates/github/workflows/ci.yml +17 -10
  20. package/templates/github/workflows/is-compatible.yml +2 -2
  21. package/templates/github/workflows/release.yml +1 -1
  22. package/dist/codemods/additions/scripts/bundle-grafana-ui/index.js +0 -174
  23. package/dist/codemods/utils.bundler-config.js +0 -19
  24. package/dist/codemods/utils.externals.js +0 -116
  25. package/src/codemods/additions/scripts/bundle-grafana-ui/README.md +0 -68
  26. package/src/codemods/additions/scripts/bundle-grafana-ui/index.test.ts +0 -511
  27. package/src/codemods/additions/scripts/bundle-grafana-ui/index.ts +0 -259
  28. package/src/codemods/utils.bundler-config.ts +0 -203
  29. package/src/codemods/utils.externals.test.ts +0 -87
  30. package/src/codemods/utils.externals.ts +0 -181
  31. package/templates/common/.config/rspack/utils.ts +0 -63
  32. package/templates/common/.config/webpack/constants.ts +0 -2
  33. /package/templates/common/.config/{rspack → bundler}/constants.ts +0 -0
  34. /package/templates/common/.config/{webpack → bundler}/utils.ts +0 -0
@@ -17,65 +17,67 @@
17
17
  "license": "Apache-2.0",
18
18
  "devDependencies": {
19
19
  "@grafana/eslint-config": "^9.0.0",
20
- "@grafana/plugin-e2e": "^3.1.0",
20
+ "@grafana/plugin-e2e": "^3.2.0",
21
21
  "@grafana/tsconfig": "^2.0.1",
22
- "@playwright/test": "^1.52.0",{{#if useExperimentalRspack}}
23
- "@rspack/core": "^1.3.0",
24
- "@rspack/cli": "^1.3.0",{{/if}}
25
- "@stylistic/eslint-plugin-ts": "^2.9.0",
26
- "@swc/core": "^1.14.0",
22
+ "@playwright/test": "^1.57.0",{{#if useExperimentalRspack}}
23
+ "@rspack/core": "^1.6.0",
24
+ "@rspack/cli": "^1.6.0",{{/if}}
25
+ "@stylistic/eslint-plugin-ts": "^4.4.0",
26
+ "@swc/core": "^1.15.0",
27
27
  "@swc/helpers": "^0.5.0",
28
- "@swc/jest": "^0.2.26",
29
- "@testing-library/jest-dom": "6.1.4",
30
- "@testing-library/react": "14.0.0",
28
+ "@swc/jest": "^0.2.0",
29
+ "@testing-library/jest-dom": "^6.6.0",
30
+ "@testing-library/react": "^16.3.0",
31
31
  "@types/jest": "^29.5.0",
32
- "@types/node": "^20.8.7",
32
+ "@types/node": "^24.0.0",
33
33
  "@types/react": "^18.3.0",
34
- "@types/react-dom": "^18.3.0",
35
- "@typescript-eslint/eslint-plugin": "^8.3.0",
36
- "@typescript-eslint/parser": "^8.3.0",{{#unless useExperimentalRspack}}
37
- "copy-webpack-plugin": "^11.0.0",{{/unless}}
38
- "css-loader": "^6.7.3",
39
- "eslint": "^9.0.0",
40
- "eslint-config-prettier": "^8.8.0",
41
- "eslint-plugin-jsdoc": "^51.2.3",
42
- "eslint-plugin-react": "^7.37.5",
34
+ "@types/react-dom": "^18.3.0",{{#if useExperimentalRspack}}
35
+ "@types/ws": "^8.18.1",{{/if}}
36
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
37
+ "@typescript-eslint/parser": "^8.38.0",{{#unless useExperimentalRspack}}
38
+ "copy-webpack-plugin": "^13.0.0",{{/unless}}
39
+ "css-loader": "^7.1.0",
40
+ "eslint": "^9.32.0",
41
+ "eslint-config-prettier": "^10.1.0",
42
+ "eslint-plugin-jsdoc": "^52.0.0",
43
+ "eslint-plugin-react": "^7.37.0",
43
44
  "eslint-plugin-react-hooks": "^7.0.0",
44
45
  "eslint-webpack-plugin": "^5.0.0",{{#unless useExperimentalRspack}}
45
- "fork-ts-checker-webpack-plugin": "^8.0.0",{{/unless}}
46
- "glob": "^10.2.7",
47
- "identity-obj-proxy": "3.0.0",
46
+ "fork-ts-checker-webpack-plugin": "^9.1.0",{{/unless}}
47
+ "glob": "^11.1.0",
48
+ "identity-obj-proxy": "^3.0.0",
48
49
  "imports-loader": "^5.0.0",
49
- "jest": "^29.5.0",
50
- "jest-environment-jsdom": "^29.5.0",
51
- "prettier": "^2.8.7",
52
- "replace-in-file-webpack-plugin": "^1.0.6",{{#if useExperimentalRspack}}
53
- "rspack-plugin-virtual-module": "^0.1.13",{{/if}}
54
- "sass": "1.63.2",
55
- "sass-loader": "13.3.1",
56
- "semver": "^7.6.3",
57
- "style-loader": "3.3.3",{{#unless useExperimentalRspack}}
58
- "swc-loader": "^0.2.3",{{/unless}}
59
- "terser-webpack-plugin": "^5.3.10",
60
- "ts-node": "^10.9.2",{{#if useExperimentalRspack}}
61
- "ts-checker-rspack-plugin": "^1.0.0",{{/if}}
62
- "typescript": "5.5.4",
63
- "webpack": "^5.94.0"{{#unless useExperimentalRspack}},
64
- "webpack-cli": "^5.1.4",
50
+ "jest": "^29.7.0",
51
+ "jest-environment-jsdom": "^29.7.0",
52
+ "prettier": "^3.6.0",
53
+ "replace-in-file-webpack-plugin": "^1.0.0",{{#if useExperimentalRspack}}
54
+ "rspack-plugin-virtual-module": "^1.0.0",{{/if}}
55
+ "sass": "^1.89.0",
56
+ "sass-loader": "^16.0.0",
57
+ "semver": "^7.7.0",
58
+ "style-loader": "^4.0.0",{{#unless useExperimentalRspack}}
59
+ "swc-loader": "^0.2.0",{{/unless}}
60
+ "terser-webpack-plugin": "^5.3.0",
61
+ "ts-node": "^10.9.0",{{#if useExperimentalRspack}}
62
+ "ts-checker-rspack-plugin": "^1.2.0",{{/if}}
63
+ "typescript": "5.9.2",
64
+ "webpack": "^5.101.0"{{#unless useExperimentalRspack}},
65
+ "webpack-cli": "^6.0.0",
65
66
  "webpack-livereload-plugin": "^3.0.2",
66
67
  "webpack-subresource-integrity": "^5.1.0",
67
- "webpack-virtual-modules": "^0.6.2"{{/unless}}
68
+ "webpack-virtual-modules": "^0.6.2"{{/unless}}{{#if useExperimentalRspack}},
69
+ "ws": "^8.13.0"{{/if}}
68
70
  },
69
71
  "engines": {
70
72
  "node": ">=22"
71
73
  },
72
74
  "dependencies": {
73
75
  "@emotion/css": "11.10.6",
74
- "@grafana/data": "^12.3.1",
75
- "@grafana/i18n": "^12.3.1",
76
- "@grafana/runtime": "^12.3.1",
77
- "@grafana/ui": "^12.3.1",
78
- "@grafana/schema": "^12.3.1",{{#if_eq pluginType "scenesapp" }}
76
+ "@grafana/data": "^12.3.2",
77
+ "@grafana/i18n": "^12.3.2",
78
+ "@grafana/runtime": "^12.3.2",
79
+ "@grafana/ui": "^12.3.2",
80
+ "@grafana/schema": "^12.3.2",{{#if_eq pluginType "scenesapp" }}
79
81
  "@grafana/scenes": "{{ scenesVersion }}",{{/if_eq}}
80
82
  "react": "^18.3.0",
81
83
  "react-dom": "^18.3.0"{{#if isAppType}},
@@ -20,7 +20,7 @@ jobs:
20
20
 
21
21
  steps:
22
22
  - name: Checkout repository
23
- uses: actions/checkout@v5
23
+ uses: actions/checkout@v6
24
24
  with:
25
25
  persist-credentials: false
26
26
 
@@ -25,7 +25,7 @@ jobs:
25
25
  env:
26
26
  GRAFANA_ACCESS_POLICY_TOKEN: $\{{ secrets.GRAFANA_ACCESS_POLICY_TOKEN }}
27
27
  steps:
28
- - uses: actions/checkout@v5
28
+ - uses: actions/checkout@v6
29
29
  with:
30
30
  persist-credentials: false
31
31
  {{#if_eq packageManagerName "pnpm"}}
@@ -63,14 +63,14 @@ jobs:
63
63
  if: steps.check-for-backend.outputs.has-backend == 'true'
64
64
  uses: actions/setup-go@v6
65
65
  with:
66
- go-version: '1.22'
66
+ go-version-file: go.mod
67
67
 
68
- - name: Test backend
68
+ - name: Lint backend
69
69
  if: steps.check-for-backend.outputs.has-backend == 'true'
70
- uses: magefile/mage-action@6f50bbb8ea47d56e62dee92392788acbc8192d0b # v3.1.0
70
+ uses: golangci/golangci-lint-action@9fae48acfc02a90574d7c304a1758ef9895495fa # v7.0.1
71
71
  with:
72
72
  version: latest
73
- args: coverage
73
+ args: ./...
74
74
 
75
75
  - name: Build backend
76
76
  if: steps.check-for-backend.outputs.has-backend == 'true'
@@ -79,6 +79,13 @@ jobs:
79
79
  version: latest
80
80
  args: buildAll
81
81
 
82
+ - name: Test backend
83
+ if: steps.check-for-backend.outputs.has-backend == 'true'
84
+ uses: magefile/mage-action@6f50bbb8ea47d56e62dee92392788acbc8192d0b # v3.1.0
85
+ with:
86
+ version: latest
87
+ args: test
88
+
82
89
  - name: Check for E2E
83
90
  id: check-for-e2e
84
91
  run: |
@@ -122,7 +129,7 @@ jobs:
122
129
  ARCHIVE: $\{{ steps.metadata.outputs.archive }}
123
130
 
124
131
  - name: Archive Build
125
- uses: actions/upload-artifact@v5
132
+ uses: actions/upload-artifact@v6
126
133
  with:
127
134
  name: $\{{ steps.metadata.outputs.plugin-id }}-$\{{ steps.metadata.outputs.plugin-version }}
128
135
  path: $\{{ steps.metadata.outputs.plugin-id }}
@@ -140,7 +147,7 @@ jobs:
140
147
  matrix: $\{{ steps.resolve-versions.outputs.matrix }}
141
148
  steps:
142
149
  - name: Checkout
143
- uses: actions/checkout@v5
150
+ uses: actions/checkout@v6
144
151
  with:
145
152
  persist-credentials: false
146
153
 
@@ -162,12 +169,12 @@ jobs:
162
169
  name: e2e test $\{{ matrix.GRAFANA_IMAGE.name }}@$\{{ matrix.GRAFANA_IMAGE.VERSION }}
163
170
  runs-on: ubuntu-latest
164
171
  steps:
165
- - uses: actions/checkout@v5
172
+ - uses: actions/checkout@v6
166
173
  with:
167
174
  persist-credentials: false
168
175
 
169
176
  - name: Download plugin
170
- uses: actions/download-artifact@v6
177
+ uses: actions/download-artifact@v7
171
178
  with:
172
179
  path: dist
173
180
  name: $\{{ needs.build.outputs.plugin-id }}-$\{{ needs.build.outputs.plugin-version }}
@@ -242,7 +249,7 @@ jobs:
242
249
  needs: [playwright-tests]
243
250
  runs-on: ubuntu-latest
244
251
  steps:
245
- - uses: actions/checkout@v5
252
+ - uses: actions/checkout@v6
246
253
  with:
247
254
  # required for playwright-gh-pages
248
255
  persist-credentials: true
@@ -7,7 +7,7 @@ jobs:
7
7
  permissions:
8
8
  contents: read
9
9
  steps:
10
- - uses: actions/checkout@v5
10
+ - uses: actions/checkout@v6
11
11
  with:
12
12
  persist-credentials: false
13
13
 
@@ -18,7 +18,7 @@ jobs:
18
18
  {{/if_eq}}
19
19
 
20
20
  - name: Setup Node.js environment
21
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
21
+ uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
22
22
  with:
23
23
  node-version: '22'
24
24
  cache: '{{ packageManagerName }}'
@@ -16,7 +16,7 @@ jobs:
16
16
  contents: write
17
17
  runs-on: ubuntu-latest
18
18
  steps:
19
- - uses: actions/checkout@v5
19
+ - uses: actions/checkout@v6
20
20
  with:
21
21
  persist-credentials: false
22
22
 
@@ -1,174 +0,0 @@
1
- import * as v from 'valibot';
2
- import * as recast from 'recast';
3
- import { coerce, gte } from 'semver';
4
- import { additionsDebug } from '../../../utils.js';
5
- import { getBundlerConfig } from '../../../utils.bundler-config.js';
6
- import { updateExternalsArray } from '../../../utils.externals.js';
7
-
8
- const { builders } = recast.types;
9
- const PLUGIN_JSON_PATH = "src/plugin.json";
10
- const MIN_GRAFANA_VERSION = "10.2.0";
11
- const schema = v.object({});
12
- function bundleGrafanaUI(context, _options) {
13
- additionsDebug("Running bundle-grafana-ui addition...");
14
- ensureMinGrafanaVersion(context);
15
- updateExternalsArray(context, createBundleGrafanaUIModifier());
16
- updateResolveExtensions(context);
17
- updateModuleRules(context);
18
- return context;
19
- }
20
- function isGrafanaRegex(element, pattern) {
21
- if (element.type === "RegExpLiteral") {
22
- const regexNode = element;
23
- return regexNode.pattern === pattern && regexNode.flags === "i";
24
- }
25
- if (element.type === "Literal" && "regex" in element && element.regex) {
26
- const regex = element.regex;
27
- return regex.pattern === pattern && regex.flags === "i";
28
- }
29
- return false;
30
- }
31
- function removeGrafanaUiAndAddReactInlineSvg(externalsArray) {
32
- let hasChanges = false;
33
- let hasGrafanaUiExternal = false;
34
- let hasReactInlineSvg = false;
35
- for (const element of externalsArray.elements) {
36
- if (!element) {
37
- continue;
38
- }
39
- if (isGrafanaRegex(element, "^@grafana\\/ui")) {
40
- hasGrafanaUiExternal = true;
41
- }
42
- if ((element.type === "Literal" || element.type === "StringLiteral") && "value" in element && typeof element.value === "string" && element.value === "react-inlinesvg") {
43
- hasReactInlineSvg = true;
44
- }
45
- }
46
- if (hasGrafanaUiExternal) {
47
- externalsArray.elements = externalsArray.elements.filter((element) => {
48
- if (!element) {
49
- return true;
50
- }
51
- return !isGrafanaRegex(element, "^@grafana\\/ui");
52
- });
53
- hasChanges = true;
54
- additionsDebug("Removed /^@grafana\\/ui/i from externals array");
55
- }
56
- if (!hasReactInlineSvg) {
57
- let insertIndex = -1;
58
- for (let i = 0; i < externalsArray.elements.length; i++) {
59
- const element = externalsArray.elements[i];
60
- if (element && isGrafanaRegex(element, "^@grafana\\/data")) {
61
- insertIndex = i + 1;
62
- break;
63
- }
64
- }
65
- if (insertIndex >= 0) {
66
- externalsArray.elements.splice(insertIndex, 0, builders.literal("react-inlinesvg"));
67
- } else {
68
- externalsArray.elements.push(builders.literal("react-inlinesvg"));
69
- }
70
- hasChanges = true;
71
- additionsDebug("Added 'react-inlinesvg' to externals array");
72
- }
73
- return hasChanges;
74
- }
75
- function createBundleGrafanaUIModifier() {
76
- return (externalsArray) => {
77
- return removeGrafanaUiAndAddReactInlineSvg(externalsArray);
78
- };
79
- }
80
- function updateResolveExtensions(context) {
81
- const config = getBundlerConfig(context);
82
- if (!config) {
83
- return;
84
- }
85
- const { path: configPath, content } = config;
86
- if (content.includes("'.mjs'") || content.includes('".mjs"')) {
87
- return;
88
- }
89
- const updated = content.replace(/(extensions:\s*\[)([^\]]+)(\])/, (match, prefix, extensions, suffix) => {
90
- if (extensions.includes(".mjs")) {
91
- return match;
92
- }
93
- return `${prefix}${extensions}, '.mjs'${suffix}`;
94
- });
95
- if (updated !== content) {
96
- context.updateFile(configPath, updated);
97
- additionsDebug("Added '.mjs' to resolve.extensions");
98
- }
99
- }
100
- function updateModuleRules(context) {
101
- const config = getBundlerConfig(context);
102
- if (!config) {
103
- return;
104
- }
105
- const { path: configPath, content } = config;
106
- if (content.includes("test: /\\.mjs$") || content.includes("test: /\\\\.mjs$")) {
107
- return;
108
- }
109
- const mjsRule = `{
110
- test: /\\.mjs$/,
111
- include: /node_modules/,
112
- resolve: {
113
- fullySpecified: false,
114
- },
115
- type: 'javascript/auto',
116
- },`;
117
- let updated = content;
118
- if (content.match(/rules:\s*\[\s*\]/)) {
119
- updated = content.replace(/(rules:\s*\[\s*)(\])/, `$1${mjsRule}
120
- $2`);
121
- } else {
122
- updated = content.replace(/(rules:\s*\[\s*)(\{[\s\S]*?\}),(\s*)/, (match, prefix, firstRule, suffix) => {
123
- if (match.includes("test: /\\.mjs$")) {
124
- return match;
125
- }
126
- return `${prefix}${firstRule},
127
- ${mjsRule}${suffix}`;
128
- });
129
- }
130
- if (updated !== content) {
131
- context.updateFile(configPath, updated);
132
- additionsDebug("Added module rule for .mjs files in node_modules with resolve.fullySpecified: false");
133
- }
134
- }
135
- function ensureMinGrafanaVersion(context) {
136
- if (!context.doesFileExist(PLUGIN_JSON_PATH)) {
137
- additionsDebug(`${PLUGIN_JSON_PATH} not found, skipping version check`);
138
- return;
139
- }
140
- const pluginJsonRaw = context.getFile(PLUGIN_JSON_PATH);
141
- if (!pluginJsonRaw) {
142
- return;
143
- }
144
- try {
145
- const pluginJson = JSON.parse(pluginJsonRaw);
146
- if (!pluginJson.dependencies) {
147
- pluginJson.dependencies = {};
148
- }
149
- const currentGrafanaDep = pluginJson.dependencies.grafanaDependency || ">=9.0.0";
150
- const currentVersion = coerce(currentGrafanaDep.replace(/^[><=]+/, ""));
151
- const minVersion = coerce(MIN_GRAFANA_VERSION);
152
- if (!currentVersion || !minVersion || !gte(currentVersion, minVersion)) {
153
- const oldVersion = pluginJson.dependencies.grafanaDependency || "not set";
154
- pluginJson.dependencies.grafanaDependency = `>=${MIN_GRAFANA_VERSION}`;
155
- context.updateFile(PLUGIN_JSON_PATH, JSON.stringify(pluginJson, null, 2));
156
- additionsDebug(
157
- `Updated grafanaDependency from "${oldVersion}" to ">=${MIN_GRAFANA_VERSION}" - bundling @grafana/ui requires Grafana ${MIN_GRAFANA_VERSION} or higher`
158
- );
159
- console.log(
160
- `
161
- \u26A0\uFE0F Updated grafanaDependency to ">=${MIN_GRAFANA_VERSION}" because bundling @grafana/ui is only supported from Grafana ${MIN_GRAFANA_VERSION} onwards.
162
- `
163
- );
164
- } else {
165
- additionsDebug(
166
- `grafanaDependency "${currentGrafanaDep}" already meets minimum requirement of ${MIN_GRAFANA_VERSION}`
167
- );
168
- }
169
- } catch (error) {
170
- additionsDebug(`Error updating ${PLUGIN_JSON_PATH}:`, error);
171
- }
172
- }
173
-
174
- export { bundleGrafanaUI as default, schema };
@@ -1,19 +0,0 @@
1
- import 'recast';
2
- import 'recast/parsers/typescript.js';
3
- import './utils.js';
4
-
5
- const WEBPACK_CONFIG_PATH = ".config/webpack/webpack.config.ts";
6
- const RSPACK_CONFIG_PATH = ".config/rspack/rspack.config.ts";
7
- function getBundlerConfig(context) {
8
- const configPath = context.doesFileExist(RSPACK_CONFIG_PATH) ? RSPACK_CONFIG_PATH : context.doesFileExist(WEBPACK_CONFIG_PATH) ? WEBPACK_CONFIG_PATH : null;
9
- if (!configPath) {
10
- return null;
11
- }
12
- const content = context.getFile(configPath);
13
- if (!content) {
14
- return null;
15
- }
16
- return { path: configPath, content };
17
- }
18
-
19
- export { getBundlerConfig };
@@ -1,116 +0,0 @@
1
- import * as recast from 'recast';
2
- import * as typeScriptParser from 'recast/parsers/typescript.js';
3
- import { additionsDebug } from './utils.js';
4
-
5
- const EXTERNALS_PATH = ".config/bundler/externals.ts";
6
- const WEBPACK_CONFIG_PATH = ".config/webpack/webpack.config.ts";
7
- function updateExternalsArray(context, modifier) {
8
- if (context.doesFileExist(EXTERNALS_PATH)) {
9
- additionsDebug(`Found ${EXTERNALS_PATH}, updating externals array...`);
10
- const externalsContent = context.getFile(EXTERNALS_PATH);
11
- if (externalsContent) {
12
- try {
13
- const ast = recast.parse(externalsContent, {
14
- parser: typeScriptParser
15
- });
16
- let hasChanges = false;
17
- recast.visit(ast, {
18
- visitVariableDeclarator(path) {
19
- const { node } = path;
20
- if (node.id.type === "Identifier" && node.id.name === "externals" && node.init && node.init.type === "ArrayExpression") {
21
- additionsDebug("Found externals array in externals.ts");
22
- if (modifier(node.init)) {
23
- hasChanges = true;
24
- }
25
- }
26
- return this.traverse(path);
27
- }
28
- });
29
- if (hasChanges) {
30
- const output = recast.print(ast, {
31
- tabWidth: 2,
32
- trailingComma: true,
33
- lineTerminator: "\n"
34
- });
35
- context.updateFile(EXTERNALS_PATH, output.code);
36
- additionsDebug(`Updated ${EXTERNALS_PATH}`);
37
- return true;
38
- }
39
- return false;
40
- } catch (error) {
41
- additionsDebug(`Error updating ${EXTERNALS_PATH}:`, error);
42
- return false;
43
- }
44
- }
45
- }
46
- additionsDebug(`Checking for ${WEBPACK_CONFIG_PATH}...`);
47
- if (context.doesFileExist(WEBPACK_CONFIG_PATH)) {
48
- additionsDebug(`Found ${WEBPACK_CONFIG_PATH}, checking for inline externals...`);
49
- const webpackContent = context.getFile(WEBPACK_CONFIG_PATH);
50
- if (webpackContent) {
51
- try {
52
- const ast = recast.parse(webpackContent, {
53
- parser: typeScriptParser
54
- });
55
- let hasChanges = false;
56
- let foundExternals = false;
57
- recast.visit(ast, {
58
- visitObjectExpression(path) {
59
- const { node } = path;
60
- const properties = node.properties;
61
- if (properties) {
62
- for (const prop of properties) {
63
- if (prop && (prop.type === "Property" || prop.type === "ObjectProperty")) {
64
- const key = "key" in prop ? prop.key : null;
65
- const value = "value" in prop ? prop.value : null;
66
- if (key && key.type === "Identifier" && key.name === "externals" && value && value.type === "ArrayExpression") {
67
- foundExternals = true;
68
- additionsDebug("Found externals property in webpack.config.ts");
69
- if (modifier(value)) {
70
- hasChanges = true;
71
- }
72
- }
73
- }
74
- }
75
- }
76
- return this.traverse(path);
77
- },
78
- visitProperty(path) {
79
- const { node } = path;
80
- if (node.key && node.key.type === "Identifier" && node.key.name === "externals" && node.value && node.value.type === "ArrayExpression") {
81
- if (!foundExternals) {
82
- foundExternals = true;
83
- additionsDebug("Found externals property in webpack.config.ts (via visitProperty)");
84
- }
85
- if (modifier(node.value)) {
86
- hasChanges = true;
87
- }
88
- }
89
- return this.traverse(path);
90
- }
91
- });
92
- if (!foundExternals) {
93
- additionsDebug("No externals property found in webpack.config.ts");
94
- }
95
- if (hasChanges) {
96
- const output = recast.print(ast, {
97
- tabWidth: 2,
98
- trailingComma: true,
99
- lineTerminator: "\n"
100
- });
101
- context.updateFile(WEBPACK_CONFIG_PATH, output.code);
102
- additionsDebug(`Updated ${WEBPACK_CONFIG_PATH}`);
103
- return true;
104
- }
105
- return false;
106
- } catch (error) {
107
- additionsDebug(`Error updating ${WEBPACK_CONFIG_PATH}:`, error);
108
- return false;
109
- }
110
- }
111
- }
112
- additionsDebug("No externals configuration found");
113
- return false;
114
- }
115
-
116
- export { updateExternalsArray };
@@ -1,68 +0,0 @@
1
- # Bundle Grafana UI Addition
2
-
3
- Configures a Grafana plugin to bundle `@grafana/ui` instead of using the version of `@grafana/ui` provided by the Grafana runtime environment.
4
-
5
- ## Usage
6
-
7
- ```bash
8
- npx @grafana/create-plugin add bundle-grafana-ui
9
- ```
10
-
11
- ## Requirements
12
-
13
- - **Grafana >= 10.2.0**: Bundling `@grafana/ui` is only supported from Grafana 10.2.0 onwards. If your plugin's `grafanaDependency` is set to a version lower than 10.2.0, the script will automatically update it to `>=10.2.0` and display a warning message.
14
-
15
- ## What This Addition Does
16
-
17
- By default, Grafana plugins use `@grafana/ui` as an external dependency provided by Grafana at runtime. This addition modifies your plugin's bundler configuration to include `@grafana/ui` in your plugin bundle instead.
18
-
19
- This addition:
20
-
21
- 1. **Updates `src/plugin.json`** - Ensures `grafanaDependency` is set to `>=10.2.0` or higher
22
- 2. **Removes `/^@grafana\/ui/i` from externals** - This tells the bundler to include `@grafana/ui` in your plugin bundle rather than expecting Grafana to provide it
23
- 3. **Adds `'react-inlinesvg'` to externals** - Since `@grafana/ui` uses `react-inlinesvg` internally and Grafana provides it at runtime, we add it to externals to avoid bundling it twice
24
- 4. **Updates bundler resolve configuration** - Adds `.mjs` to `resolve.extensions` and sets `resolve.fullySpecified: false` to handle ESM imports from `@grafana/ui` and its dependencies (e.g., `rc-picker`, `ol/format/WKT`)
25
-
26
- ## When to Use This
27
-
28
- Consider bundling `@grafana/ui` when:
29
-
30
- - You want to ensure consistent behavior across different Grafana versions
31
- - You're experiencing compatibility issues with the Grafana-provided `@grafana/ui`
32
-
33
- ## Trade-offs
34
-
35
- **Pros:**
36
-
37
- - Full control over the `@grafana/ui` version your plugin uses
38
- - Consistent behavior regardless of Grafana version
39
-
40
- **Cons:**
41
-
42
- - Larger plugin bundle size
43
- - Potential visual inconsistencies if your bundled version differs significantly from Grafana's version
44
- - You'll need to manually update `@grafana/ui` in your plugin dependencies
45
-
46
- ## Files Modified
47
-
48
- ```
49
- your-plugin/
50
- ├── src/
51
- │ └── plugin.json # Modified: grafanaDependency updated if needed
52
- ├── .config/
53
- │ ├── bundler/
54
- │ │ └── externals.ts # Modified: removes @grafana/ui, adds react-inlinesvg
55
- │ └── rspack/
56
- │ └── rspack.config.ts # Modified: resolve.extensions and resolve.fullySpecified updated
57
- ```
58
-
59
- Or for legacy structure:
60
-
61
- ```
62
- your-plugin/
63
- ├── src/
64
- │ └── plugin.json # Modified: grafanaDependency updated if needed
65
- ├── .config/
66
- │ └── webpack/
67
- │ └── webpack.config.ts # Modified: externals array and resolve configuration updated
68
- ```