@grafana/create-plugin 6.8.0-canary.2356.20813734793.0 → 6.8.0-canary.2356.20813982803.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.
- package/CHANGELOG.md +12 -0
- package/dist/codemods/additions/scripts/bundle-grafana-ui/index.js +67 -116
- package/package.json +2 -2
- package/src/codemods/additions/scripts/bundle-grafana-ui/index.ts +97 -165
- package/templates/common/.config/rspack/rspack.config.ts +9 -9
- package/templates/common/.config/webpack/webpack.config.ts +7 -7
- package/dist/codemods/utils.bundler-config.js +0 -102
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# v6.7.1 (Thu Jan 08 2026)
|
|
2
|
+
|
|
3
|
+
#### 🐛 Bug Fix
|
|
4
|
+
|
|
5
|
+
- fix: stop copying all images to bundle [#2369](https://github.com/grafana/plugin-tools/pull/2369) ([@jackw](https://github.com/jackw))
|
|
6
|
+
|
|
7
|
+
#### Authors: 1
|
|
8
|
+
|
|
9
|
+
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
1
13
|
# v6.7.0 (Wed Jan 07 2026)
|
|
2
14
|
|
|
3
15
|
#### 🚀 Enhancement
|
|
@@ -2,39 +2,30 @@ import * as v from 'valibot';
|
|
|
2
2
|
import * as recast from 'recast';
|
|
3
3
|
import { coerce, gte } from 'semver';
|
|
4
4
|
import { additionsDebug } from '../../../utils.js';
|
|
5
|
-
import { updateBundlerConfig } from '../../../utils.bundler-config.js';
|
|
6
5
|
import { updateExternalsArray } from '../../../utils.externals.js';
|
|
7
6
|
|
|
8
7
|
const { builders } = recast.types;
|
|
9
8
|
const PLUGIN_JSON_PATH = "src/plugin.json";
|
|
10
9
|
const MIN_GRAFANA_VERSION = "10.2.0";
|
|
10
|
+
const WEBPACK_CONFIG_PATH = ".config/webpack/webpack.config.ts";
|
|
11
|
+
const RSPACK_CONFIG_PATH = ".config/rspack/rspack.config.ts";
|
|
11
12
|
const schema = v.object({});
|
|
12
13
|
function bundleGrafanaUI(context, _options) {
|
|
13
14
|
additionsDebug("Running bundle-grafana-ui addition...");
|
|
14
15
|
ensureMinGrafanaVersion(context);
|
|
15
16
|
updateExternalsArray(context, createBundleGrafanaUIModifier());
|
|
16
|
-
|
|
17
|
+
updateResolveExtensionsSimple(context);
|
|
18
|
+
updateModuleRulesSimple(context);
|
|
17
19
|
return context;
|
|
18
20
|
}
|
|
19
|
-
function
|
|
21
|
+
function isGrafanaRegex(element, pattern) {
|
|
20
22
|
if (element.type === "RegExpLiteral") {
|
|
21
23
|
const regexNode = element;
|
|
22
|
-
return regexNode.pattern ===
|
|
24
|
+
return regexNode.pattern === pattern && regexNode.flags === "i";
|
|
23
25
|
}
|
|
24
26
|
if (element.type === "Literal" && "regex" in element && element.regex) {
|
|
25
27
|
const regex = element.regex;
|
|
26
|
-
return regex.pattern ===
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
function isGrafanaDataRegex(element) {
|
|
31
|
-
if (element.type === "RegExpLiteral") {
|
|
32
|
-
const regexNode = element;
|
|
33
|
-
return regexNode.pattern === "^@grafana\\/data" && regexNode.flags === "i";
|
|
34
|
-
}
|
|
35
|
-
if (element.type === "Literal" && "regex" in element && element.regex) {
|
|
36
|
-
const regex = element.regex;
|
|
37
|
-
return regex.pattern === "^@grafana\\/data" && regex.flags === "i";
|
|
28
|
+
return regex.pattern === pattern && regex.flags === "i";
|
|
38
29
|
}
|
|
39
30
|
return false;
|
|
40
31
|
}
|
|
@@ -46,7 +37,7 @@ function removeGrafanaUiAndAddReactInlineSvg(externalsArray) {
|
|
|
46
37
|
if (!element) {
|
|
47
38
|
continue;
|
|
48
39
|
}
|
|
49
|
-
if (
|
|
40
|
+
if (isGrafanaRegex(element, "^@grafana\\/ui")) {
|
|
50
41
|
hasGrafanaUiExternal = true;
|
|
51
42
|
}
|
|
52
43
|
if ((element.type === "Literal" || element.type === "StringLiteral") && "value" in element && typeof element.value === "string" && element.value === "react-inlinesvg") {
|
|
@@ -58,7 +49,7 @@ function removeGrafanaUiAndAddReactInlineSvg(externalsArray) {
|
|
|
58
49
|
if (!element) {
|
|
59
50
|
return true;
|
|
60
51
|
}
|
|
61
|
-
return !
|
|
52
|
+
return !isGrafanaRegex(element, "^@grafana\\/ui");
|
|
62
53
|
});
|
|
63
54
|
hasChanges = true;
|
|
64
55
|
additionsDebug("Removed /^@grafana\\/ui/i from externals array");
|
|
@@ -67,7 +58,7 @@ function removeGrafanaUiAndAddReactInlineSvg(externalsArray) {
|
|
|
67
58
|
let insertIndex = -1;
|
|
68
59
|
for (let i = 0; i < externalsArray.elements.length; i++) {
|
|
69
60
|
const element = externalsArray.elements[i];
|
|
70
|
-
if (element &&
|
|
61
|
+
if (element && isGrafanaRegex(element, "^@grafana\\/data")) {
|
|
71
62
|
insertIndex = i + 1;
|
|
72
63
|
break;
|
|
73
64
|
}
|
|
@@ -87,106 +78,66 @@ function createBundleGrafanaUIModifier() {
|
|
|
87
78
|
return removeGrafanaUiAndAddReactInlineSvg(externalsArray);
|
|
88
79
|
};
|
|
89
80
|
}
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (key.name === "extensions" && value && value.type === "ArrayExpression") {
|
|
106
|
-
extensionsProperty = prop;
|
|
107
|
-
for (const element of value.elements) {
|
|
108
|
-
if (element && (element.type === "Literal" || element.type === "StringLiteral") && "value" in element && element.value === ".mjs") {
|
|
109
|
-
hasMjsExtension = true;
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (!hasMjsExtension && extensionsProperty && "value" in extensionsProperty) {
|
|
117
|
-
const extensionsArray = extensionsProperty.value;
|
|
118
|
-
extensionsArray.elements.push(builders.literal(".mjs"));
|
|
119
|
-
hasChanges = true;
|
|
120
|
-
additionsDebug("Added '.mjs' to resolve.extensions");
|
|
81
|
+
function updateResolveExtensionsSimple(context) {
|
|
82
|
+
const configPath = context.doesFileExist(RSPACK_CONFIG_PATH) ? RSPACK_CONFIG_PATH : context.doesFileExist(WEBPACK_CONFIG_PATH) ? WEBPACK_CONFIG_PATH : null;
|
|
83
|
+
if (!configPath) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const content = context.getFile(configPath);
|
|
87
|
+
if (!content) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (content.includes("'.mjs'") || content.includes('".mjs"')) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const updated = content.replace(/(extensions:\s*\[)([^\]]+)(\])/, (match, prefix, extensions, suffix) => {
|
|
94
|
+
if (extensions.includes(".mjs")) {
|
|
95
|
+
return match;
|
|
121
96
|
}
|
|
122
|
-
return
|
|
123
|
-
};
|
|
97
|
+
return `${prefix}${extensions}, '.mjs'${suffix}`;
|
|
98
|
+
});
|
|
99
|
+
if (updated !== content) {
|
|
100
|
+
context.updateFile(configPath, updated);
|
|
101
|
+
additionsDebug("Added '.mjs' to resolve.extensions");
|
|
102
|
+
}
|
|
124
103
|
}
|
|
125
|
-
function
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
if (testValue.type === "Literal" && "value" in testValue && typeof testValue.value === "string" && testValue.value.includes(".mjs")) {
|
|
156
|
-
hasMjsRule = true;
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
if (hasMjsRule) {
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
break;
|
|
104
|
+
function updateModuleRulesSimple(context) {
|
|
105
|
+
const configPath = context.doesFileExist(RSPACK_CONFIG_PATH) ? RSPACK_CONFIG_PATH : context.doesFileExist(WEBPACK_CONFIG_PATH) ? WEBPACK_CONFIG_PATH : null;
|
|
106
|
+
if (!configPath) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const content = context.getFile(configPath);
|
|
110
|
+
if (!content) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (content.includes("test: /\\.mjs$") || content.includes("test: /\\\\.mjs$")) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const mjsRule = `{
|
|
117
|
+
test: /\\.mjs$/,
|
|
118
|
+
include: /node_modules/,
|
|
119
|
+
resolve: {
|
|
120
|
+
fullySpecified: false,
|
|
121
|
+
},
|
|
122
|
+
type: 'javascript/auto',
|
|
123
|
+
},`;
|
|
124
|
+
let updated = content;
|
|
125
|
+
if (content.match(/rules:\s*\[\s*\]/)) {
|
|
126
|
+
updated = content.replace(/(rules:\s*\[\s*)(\])/, `$1${mjsRule}
|
|
127
|
+
$2`);
|
|
128
|
+
} else {
|
|
129
|
+
updated = content.replace(/(rules:\s*\[\s*)(\{[\s\S]*?\}),(\s*)/, (match, prefix, firstRule, suffix) => {
|
|
130
|
+
if (match.includes("test: /\\.mjs$")) {
|
|
131
|
+
return match;
|
|
168
132
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
builders.identifier("resolve"),
|
|
178
|
-
builders.objectExpression([
|
|
179
|
-
builders.property("init", builders.identifier("fullySpecified"), builders.literal(false))
|
|
180
|
-
])
|
|
181
|
-
),
|
|
182
|
-
builders.property("init", builders.identifier("type"), builders.literal("javascript/auto"))
|
|
183
|
-
]);
|
|
184
|
-
rulesArray.elements.splice(1, 0, mjsRule);
|
|
185
|
-
hasChanges = true;
|
|
186
|
-
additionsDebug("Added module rule for .mjs files in node_modules with resolve.fullySpecified: false");
|
|
187
|
-
}
|
|
188
|
-
return hasChanges;
|
|
189
|
-
};
|
|
133
|
+
return `${prefix}${firstRule},
|
|
134
|
+
${mjsRule}${suffix}`;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (updated !== content) {
|
|
138
|
+
context.updateFile(configPath, updated);
|
|
139
|
+
additionsDebug("Added module rule for .mjs files in node_modules with resolve.fullySpecified: false");
|
|
140
|
+
}
|
|
190
141
|
}
|
|
191
142
|
function ensureMinGrafanaVersion(context) {
|
|
192
143
|
if (!context.doesFileExist(PLUGIN_JSON_PATH)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafana/create-plugin",
|
|
3
|
-
"version": "6.8.0-canary.2356.
|
|
3
|
+
"version": "6.8.0-canary.2356.20813982803.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"directory": "packages/create-plugin",
|
|
6
6
|
"url": "https://github.com/grafana/plugin-tools"
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=20"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "fedff1c23ee3079d90f0ed2d6984c78fb294b1b9"
|
|
59
59
|
}
|
|
@@ -4,13 +4,14 @@ import { coerce, gte } from 'semver';
|
|
|
4
4
|
|
|
5
5
|
import type { Context } from '../../../context.js';
|
|
6
6
|
import { additionsDebug } from '../../../utils.js';
|
|
7
|
-
import { updateBundlerConfig, type ModuleRulesModifier, type ResolveModifier } from '../../../utils.bundler-config.js';
|
|
8
7
|
import { updateExternalsArray, type ExternalsArrayModifier } from '../../../utils.externals.js';
|
|
9
8
|
|
|
10
9
|
const { builders } = recast.types;
|
|
11
10
|
|
|
12
11
|
const PLUGIN_JSON_PATH = 'src/plugin.json';
|
|
13
12
|
const MIN_GRAFANA_VERSION = '10.2.0';
|
|
13
|
+
const WEBPACK_CONFIG_PATH = '.config/webpack/webpack.config.ts';
|
|
14
|
+
const RSPACK_CONFIG_PATH = '.config/rspack/rspack.config.ts';
|
|
14
15
|
|
|
15
16
|
export const schema = v.object({});
|
|
16
17
|
type BundleGrafanaUIOptions = v.InferOutput<typeof schema>;
|
|
@@ -25,43 +26,29 @@ export default function bundleGrafanaUI(context: Context, _options: BundleGrafan
|
|
|
25
26
|
updateExternalsArray(context, createBundleGrafanaUIModifier());
|
|
26
27
|
|
|
27
28
|
// Update bundler resolve configuration to handle ESM imports
|
|
28
|
-
|
|
29
|
+
updateResolveExtensionsSimple(context);
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
// Update module rules directly with simple string manipulation
|
|
32
|
+
updateModuleRulesSimple(context);
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
* Checks if an AST node is a regex matching @grafana/ui
|
|
35
|
-
* The pattern in the AST is "^@grafana\/ui" (backslash-escaped forward slash)
|
|
36
|
-
*/
|
|
37
|
-
function isGrafanaUiRegex(element: recast.types.namedTypes.ASTNode): boolean {
|
|
38
|
-
// Handle RegExpLiteral (TypeScript parser)
|
|
39
|
-
if (element.type === 'RegExpLiteral') {
|
|
40
|
-
const regexNode = element as recast.types.namedTypes.RegExpLiteral;
|
|
41
|
-
return regexNode.pattern === '^@grafana\\/ui' && regexNode.flags === 'i';
|
|
42
|
-
}
|
|
43
|
-
// Handle Literal with regex property (other parsers)
|
|
44
|
-
if (element.type === 'Literal' && 'regex' in element && element.regex) {
|
|
45
|
-
const regex = element.regex as { pattern: string; flags: string };
|
|
46
|
-
return regex.pattern === '^@grafana\\/ui' && regex.flags === 'i';
|
|
47
|
-
}
|
|
48
|
-
return false;
|
|
34
|
+
return context;
|
|
49
35
|
}
|
|
50
36
|
|
|
51
37
|
/**
|
|
52
|
-
* Checks if an AST node is a regex matching
|
|
53
|
-
*
|
|
38
|
+
* Checks if an AST node is a regex matching a Grafana package pattern
|
|
39
|
+
* @param element - The AST node to check
|
|
40
|
+
* @param pattern - The regex pattern to match (e.g., "^@grafana\\/ui" or "^@grafana\\/data")
|
|
54
41
|
*/
|
|
55
|
-
function
|
|
42
|
+
function isGrafanaRegex(element: recast.types.namedTypes.ASTNode, pattern: string): boolean {
|
|
56
43
|
// Handle RegExpLiteral (TypeScript parser)
|
|
57
44
|
if (element.type === 'RegExpLiteral') {
|
|
58
45
|
const regexNode = element as recast.types.namedTypes.RegExpLiteral;
|
|
59
|
-
return regexNode.pattern ===
|
|
46
|
+
return regexNode.pattern === pattern && regexNode.flags === 'i';
|
|
60
47
|
}
|
|
61
48
|
// Handle Literal with regex property (other parsers)
|
|
62
49
|
if (element.type === 'Literal' && 'regex' in element && element.regex) {
|
|
63
50
|
const regex = element.regex as { pattern: string; flags: string };
|
|
64
|
-
return regex.pattern ===
|
|
51
|
+
return regex.pattern === pattern && regex.flags === 'i';
|
|
65
52
|
}
|
|
66
53
|
return false;
|
|
67
54
|
}
|
|
@@ -82,7 +69,7 @@ function removeGrafanaUiAndAddReactInlineSvg(externalsArray: recast.types.namedT
|
|
|
82
69
|
}
|
|
83
70
|
|
|
84
71
|
// Check for /^@grafana\/ui/i regex
|
|
85
|
-
if (
|
|
72
|
+
if (isGrafanaRegex(element, '^@grafana\\/ui')) {
|
|
86
73
|
hasGrafanaUiExternal = true;
|
|
87
74
|
}
|
|
88
75
|
|
|
@@ -103,7 +90,7 @@ function removeGrafanaUiAndAddReactInlineSvg(externalsArray: recast.types.namedT
|
|
|
103
90
|
if (!element) {
|
|
104
91
|
return true;
|
|
105
92
|
}
|
|
106
|
-
return !
|
|
93
|
+
return !isGrafanaRegex(element, '^@grafana\\/ui');
|
|
107
94
|
});
|
|
108
95
|
hasChanges = true;
|
|
109
96
|
additionsDebug('Removed /^@grafana\\/ui/i from externals array');
|
|
@@ -115,7 +102,7 @@ function removeGrafanaUiAndAddReactInlineSvg(externalsArray: recast.types.namedT
|
|
|
115
102
|
let insertIndex = -1;
|
|
116
103
|
for (let i = 0; i < externalsArray.elements.length; i++) {
|
|
117
104
|
const element = externalsArray.elements[i];
|
|
118
|
-
if (element &&
|
|
105
|
+
if (element && isGrafanaRegex(element, '^@grafana\\/data')) {
|
|
119
106
|
insertIndex = i + 1;
|
|
120
107
|
break;
|
|
121
108
|
}
|
|
@@ -145,158 +132,103 @@ function createBundleGrafanaUIModifier(): ExternalsArrayModifier {
|
|
|
145
132
|
}
|
|
146
133
|
|
|
147
134
|
/**
|
|
148
|
-
*
|
|
135
|
+
* Updates resolve extensions to add .mjs using simple string manipulation
|
|
136
|
+
* This is a simplified approach that may not handle all edge cases, but is much simpler
|
|
149
137
|
*/
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
138
|
+
function updateResolveExtensionsSimple(context: Context): void {
|
|
139
|
+
const configPath = context.doesFileExist(RSPACK_CONFIG_PATH)
|
|
140
|
+
? RSPACK_CONFIG_PATH
|
|
141
|
+
: context.doesFileExist(WEBPACK_CONFIG_PATH)
|
|
142
|
+
? WEBPACK_CONFIG_PATH
|
|
143
|
+
: null;
|
|
144
|
+
|
|
145
|
+
if (!configPath) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
159
148
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
149
|
+
const content = context.getFile(configPath);
|
|
150
|
+
if (!content) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
165
153
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (key.name === 'extensions' && value && value.type === 'ArrayExpression') {
|
|
171
|
-
extensionsProperty = prop as recast.types.namedTypes.Property;
|
|
172
|
-
// Check if .mjs is already in the extensions array
|
|
173
|
-
for (const element of value.elements) {
|
|
174
|
-
if (
|
|
175
|
-
element &&
|
|
176
|
-
(element.type === 'Literal' || element.type === 'StringLiteral') &&
|
|
177
|
-
'value' in element &&
|
|
178
|
-
element.value === '.mjs'
|
|
179
|
-
) {
|
|
180
|
-
hasMjsExtension = true;
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
154
|
+
// Check if .mjs already exists
|
|
155
|
+
if (content.includes("'.mjs'") || content.includes('".mjs"')) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
187
158
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
hasChanges = true;
|
|
193
|
-
additionsDebug("Added '.mjs' to resolve.extensions");
|
|
159
|
+
// Add .mjs to extensions array
|
|
160
|
+
const updated = content.replace(/(extensions:\s*\[)([^\]]+)(\])/, (match, prefix, extensions, suffix) => {
|
|
161
|
+
if (extensions.includes('.mjs')) {
|
|
162
|
+
return match;
|
|
194
163
|
}
|
|
164
|
+
return `${prefix}${extensions}, '.mjs'${suffix}`;
|
|
165
|
+
});
|
|
195
166
|
|
|
196
|
-
|
|
197
|
-
|
|
167
|
+
if (updated !== content) {
|
|
168
|
+
context.updateFile(configPath, updated);
|
|
169
|
+
additionsDebug("Added '.mjs' to resolve.extensions");
|
|
170
|
+
}
|
|
198
171
|
}
|
|
199
172
|
|
|
200
173
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
174
|
+
* Updates module rules to add .mjs rule using simple string manipulation
|
|
175
|
+
* This is a simplified approach that may not handle all edge cases, but is much simpler
|
|
203
176
|
*/
|
|
204
|
-
function
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
177
|
+
function updateModuleRulesSimple(context: Context): void {
|
|
178
|
+
const configPath = context.doesFileExist(RSPACK_CONFIG_PATH)
|
|
179
|
+
? RSPACK_CONFIG_PATH
|
|
180
|
+
: context.doesFileExist(WEBPACK_CONFIG_PATH)
|
|
181
|
+
? WEBPACK_CONFIG_PATH
|
|
182
|
+
: null;
|
|
183
|
+
|
|
184
|
+
if (!configPath) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
209
187
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
188
|
+
const content = context.getFile(configPath);
|
|
189
|
+
if (!content) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
213
192
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
193
|
+
// Check if rule already exists
|
|
194
|
+
if (content.includes('test: /\\.mjs$') || content.includes('test: /\\\\.mjs$')) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
219
197
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
if (
|
|
245
|
-
testValue.type === 'Literal' &&
|
|
246
|
-
'regex' in testValue &&
|
|
247
|
-
testValue.regex &&
|
|
248
|
-
typeof testValue.regex === 'object' &&
|
|
249
|
-
'pattern' in testValue.regex &&
|
|
250
|
-
testValue.regex.pattern === '\\.mjs$'
|
|
251
|
-
) {
|
|
252
|
-
hasMjsRule = true;
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
// Check for string literal containing .mjs
|
|
256
|
-
if (
|
|
257
|
-
testValue.type === 'Literal' &&
|
|
258
|
-
'value' in testValue &&
|
|
259
|
-
typeof testValue.value === 'string' &&
|
|
260
|
-
testValue.value.includes('.mjs')
|
|
261
|
-
) {
|
|
262
|
-
hasMjsRule = true;
|
|
263
|
-
break;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
if (hasMjsRule) {
|
|
270
|
-
break;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
break;
|
|
198
|
+
const mjsRule = `{
|
|
199
|
+
test: /\\.mjs$/,
|
|
200
|
+
include: /node_modules/,
|
|
201
|
+
resolve: {
|
|
202
|
+
fullySpecified: false,
|
|
203
|
+
},
|
|
204
|
+
type: 'javascript/auto',
|
|
205
|
+
},`;
|
|
206
|
+
|
|
207
|
+
// Simple approach: find rules array and insert after first rule
|
|
208
|
+
let updated = content;
|
|
209
|
+
|
|
210
|
+
// Case 1: Empty array - insert at start
|
|
211
|
+
if (content.match(/rules:\s*\[\s*\]/)) {
|
|
212
|
+
updated = content.replace(/(rules:\s*\[\s*)(\])/, `$1${mjsRule}\n $2`);
|
|
213
|
+
}
|
|
214
|
+
// Case 2: Find first rule and insert after it
|
|
215
|
+
else {
|
|
216
|
+
// Match: rules: [ { ... }, and insert mjs rule after the first rule
|
|
217
|
+
// The regex finds the first complete rule object (balanced braces)
|
|
218
|
+
updated = content.replace(/(rules:\s*\[\s*)(\{[\s\S]*?\}),(\s*)/, (match, prefix, firstRule, suffix) => {
|
|
219
|
+
// Check if we already inserted (avoid double insertion)
|
|
220
|
+
if (match.includes('test: /\\.mjs$')) {
|
|
221
|
+
return match;
|
|
274
222
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const rulesArray = rulesProperty.value as recast.types.namedTypes.ArrayExpression;
|
|
280
|
-
const mjsRule = builders.objectExpression([
|
|
281
|
-
builders.property('init', builders.identifier('test'), builders.literal(/\.mjs$/)),
|
|
282
|
-
builders.property('init', builders.identifier('include'), builders.literal(/node_modules/)),
|
|
283
|
-
builders.property(
|
|
284
|
-
'init',
|
|
285
|
-
builders.identifier('resolve'),
|
|
286
|
-
builders.objectExpression([
|
|
287
|
-
builders.property('init', builders.identifier('fullySpecified'), builders.literal(false)),
|
|
288
|
-
])
|
|
289
|
-
),
|
|
290
|
-
builders.property('init', builders.identifier('type'), builders.literal('javascript/auto')),
|
|
291
|
-
]);
|
|
292
|
-
// Insert at position 1 (second position) to keep imports-loader first
|
|
293
|
-
rulesArray.elements.splice(1, 0, mjsRule);
|
|
294
|
-
hasChanges = true;
|
|
295
|
-
additionsDebug('Added module rule for .mjs files in node_modules with resolve.fullySpecified: false');
|
|
296
|
-
}
|
|
223
|
+
// Insert mjs rule after first rule
|
|
224
|
+
return `${prefix}${firstRule},\n ${mjsRule}${suffix}`;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
297
227
|
|
|
298
|
-
|
|
299
|
-
|
|
228
|
+
if (updated !== content) {
|
|
229
|
+
context.updateFile(configPath, updated);
|
|
230
|
+
additionsDebug('Added module rule for .mjs files in node_modules with resolve.fullySpecified: false');
|
|
231
|
+
}
|
|
300
232
|
}
|
|
301
233
|
|
|
302
234
|
/**
|
|
@@ -21,7 +21,8 @@ import { externals } from '../bundler/externals';
|
|
|
21
21
|
const { SubresourceIntegrityPlugin } = rspack.experiments;
|
|
22
22
|
const pluginJson = getPluginJson();
|
|
23
23
|
const cpVersion = getCPConfigVersion();
|
|
24
|
-
|
|
24
|
+
const logoPaths = Array.from(new Set([pluginJson.info?.logos?.large, pluginJson.info?.logos?.small])).filter(Boolean);
|
|
25
|
+
const screenshotPaths = pluginJson.info?.screenshots?.map((s: { path: string }) => s.path) || [];
|
|
25
26
|
const virtualPublicPath = new RspackVirtualModulePlugin({
|
|
26
27
|
'grafana-public-path': `
|
|
27
28
|
import amdMetaModule from 'amd-module';
|
|
@@ -161,14 +162,13 @@ const config = async (env): Promise<Configuration> => {
|
|
|
161
162
|
{ from: 'plugin.json', to: '.' },
|
|
162
163
|
{ from: '../LICENSE', to: '.' },
|
|
163
164
|
{ from: '../CHANGELOG.md', to: '.', force: true },
|
|
164
|
-
{ from: '**/*.json', to: '.' },
|
|
165
|
-
{ from: '
|
|
166
|
-
{ from:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
{ from: '**/query_help.md', to: '.', noErrorOnMissing: true }, // Optional
|
|
165
|
+
{ from: '**/*.json', to: '.' },
|
|
166
|
+
{ from: '**/query_help.md', to: '.', noErrorOnMissing: true },
|
|
167
|
+
...logoPaths.map((logoPath) => ({ from: logoPath, to: logoPath })),
|
|
168
|
+
...screenshotPaths.map((screenshotPath) => ({
|
|
169
|
+
from: screenshotPath,
|
|
170
|
+
to: screenshotPath,
|
|
171
|
+
})),
|
|
172
172
|
],
|
|
173
173
|
}),
|
|
174
174
|
// Replace certain template-variables in the README and plugin.json
|
|
@@ -24,7 +24,8 @@ import { externals } from '../bundler/externals.ts';
|
|
|
24
24
|
const pluginJson = getPluginJson();
|
|
25
25
|
const cpVersion = getCPConfigVersion();
|
|
26
26
|
const pluginVersion = getPackageJson().version;
|
|
27
|
-
|
|
27
|
+
const logoPaths = Array.from(new Set([pluginJson.info?.logos?.large, pluginJson.info?.logos?.small])).filter(Boolean);
|
|
28
|
+
const screenshotPaths = pluginJson.info?.screenshots?.map((s: { path: string }) => s.path) || [];
|
|
28
29
|
const virtualPublicPath = new VirtualModulesPlugin({
|
|
29
30
|
'node_modules/grafana-public-path.js': `
|
|
30
31
|
import amdMetaModule from 'amd-module';
|
|
@@ -174,13 +175,12 @@ const config = async (env: Env): Promise<Configuration> => {
|
|
|
174
175
|
{ from: '../LICENSE', to: '.' },
|
|
175
176
|
{ from: '../CHANGELOG.md', to: '.', force: true },
|
|
176
177
|
{ from: '**/*.json', to: '.' },
|
|
177
|
-
{ from: '**/*.svg', to: '.', noErrorOnMissing: true },
|
|
178
|
-
{ from: '**/*.png', to: '.', noErrorOnMissing: true },
|
|
179
|
-
{ from: '**/*.html', to: '.', noErrorOnMissing: true },
|
|
180
|
-
{ from: 'img/**/*', to: '.', noErrorOnMissing: true },
|
|
181
|
-
{ from: 'libs/**/*', to: '.', noErrorOnMissing: true },
|
|
182
|
-
{ from: 'static/**/*', to: '.', noErrorOnMissing: true },
|
|
183
178
|
{ from: '**/query_help.md', to: '.', noErrorOnMissing: true },
|
|
179
|
+
...logoPaths.map((logoPath) => ({ from: logoPath, to: logoPath })),
|
|
180
|
+
...screenshotPaths.map((screenshotPath) => ({
|
|
181
|
+
from: screenshotPath,
|
|
182
|
+
to: screenshotPath,
|
|
183
|
+
})),
|
|
184
184
|
],
|
|
185
185
|
}),
|
|
186
186
|
// Replace certain template-variables in the README and plugin.json
|
|
@@ -1,102 +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 WEBPACK_CONFIG_PATH = ".config/webpack/webpack.config.ts";
|
|
6
|
-
const RSPACK_CONFIG_PATH = ".config/rspack/rspack.config.ts";
|
|
7
|
-
function updateBundlerConfig(context, resolveModifier, moduleRulesModifier) {
|
|
8
|
-
if (!resolveModifier && !moduleRulesModifier) {
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
if (context.doesFileExist(RSPACK_CONFIG_PATH)) {
|
|
12
|
-
additionsDebug(`Found ${RSPACK_CONFIG_PATH}, updating bundler configuration...`);
|
|
13
|
-
const rspackContent = context.getFile(RSPACK_CONFIG_PATH);
|
|
14
|
-
if (rspackContent) {
|
|
15
|
-
try {
|
|
16
|
-
const ast = recast.parse(rspackContent, {
|
|
17
|
-
parser: typeScriptParser
|
|
18
|
-
});
|
|
19
|
-
let hasChanges = false;
|
|
20
|
-
recast.visit(ast, {
|
|
21
|
-
visitObjectExpression(path) {
|
|
22
|
-
const { node } = path;
|
|
23
|
-
const properties = node.properties;
|
|
24
|
-
if (properties) {
|
|
25
|
-
for (const prop of properties) {
|
|
26
|
-
if (prop && (prop.type === "Property" || prop.type === "ObjectProperty")) {
|
|
27
|
-
const key = "key" in prop ? prop.key : null;
|
|
28
|
-
const value = "value" in prop ? prop.value : null;
|
|
29
|
-
if (resolveModifier && key && key.type === "Identifier" && key.name === "resolve" && value && value.type === "ObjectExpression") {
|
|
30
|
-
hasChanges = resolveModifier(value) || hasChanges;
|
|
31
|
-
}
|
|
32
|
-
if (moduleRulesModifier && key && key.type === "Identifier" && key.name === "module" && value && value.type === "ObjectExpression") {
|
|
33
|
-
hasChanges = moduleRulesModifier(value) || hasChanges;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return this.traverse(path);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
if (hasChanges) {
|
|
42
|
-
const output = recast.print(ast, {
|
|
43
|
-
tabWidth: 2,
|
|
44
|
-
trailingComma: true,
|
|
45
|
-
lineTerminator: "\n"
|
|
46
|
-
});
|
|
47
|
-
context.updateFile(RSPACK_CONFIG_PATH, output.code);
|
|
48
|
-
additionsDebug(`Updated ${RSPACK_CONFIG_PATH}`);
|
|
49
|
-
}
|
|
50
|
-
} catch (error) {
|
|
51
|
-
additionsDebug(`Error updating ${RSPACK_CONFIG_PATH}:`, error);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (context.doesFileExist(WEBPACK_CONFIG_PATH)) {
|
|
57
|
-
additionsDebug(`Found ${WEBPACK_CONFIG_PATH}, updating bundler configuration...`);
|
|
58
|
-
const webpackContent = context.getFile(WEBPACK_CONFIG_PATH);
|
|
59
|
-
if (webpackContent) {
|
|
60
|
-
try {
|
|
61
|
-
const ast = recast.parse(webpackContent, {
|
|
62
|
-
parser: typeScriptParser
|
|
63
|
-
});
|
|
64
|
-
let hasChanges = false;
|
|
65
|
-
recast.visit(ast, {
|
|
66
|
-
visitObjectExpression(path) {
|
|
67
|
-
const { node } = path;
|
|
68
|
-
const properties = node.properties;
|
|
69
|
-
if (properties) {
|
|
70
|
-
for (const prop of properties) {
|
|
71
|
-
if (prop && (prop.type === "Property" || prop.type === "ObjectProperty")) {
|
|
72
|
-
const key = "key" in prop ? prop.key : null;
|
|
73
|
-
const value = "value" in prop ? prop.value : null;
|
|
74
|
-
if (resolveModifier && key && key.type === "Identifier" && key.name === "resolve" && value && value.type === "ObjectExpression") {
|
|
75
|
-
hasChanges = resolveModifier(value) || hasChanges;
|
|
76
|
-
}
|
|
77
|
-
if (moduleRulesModifier && key && key.type === "Identifier" && key.name === "module" && value && value.type === "ObjectExpression") {
|
|
78
|
-
hasChanges = moduleRulesModifier(value) || hasChanges;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return this.traverse(path);
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
if (hasChanges) {
|
|
87
|
-
const output = recast.print(ast, {
|
|
88
|
-
tabWidth: 2,
|
|
89
|
-
trailingComma: true,
|
|
90
|
-
lineTerminator: "\n"
|
|
91
|
-
});
|
|
92
|
-
context.updateFile(WEBPACK_CONFIG_PATH, output.code);
|
|
93
|
-
additionsDebug(`Updated ${WEBPACK_CONFIG_PATH}`);
|
|
94
|
-
}
|
|
95
|
-
} catch (error) {
|
|
96
|
-
additionsDebug(`Error updating ${WEBPACK_CONFIG_PATH}:`, error);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export { updateBundlerConfig };
|