@grafana/create-plugin 6.5.0-canary.2320.20267963205.0 → 6.5.0-canary.2320.20268376971.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.
@@ -54,23 +54,23 @@ function addI18nInitialization(context, needsBackwardCompatibility) {
54
54
  )
55
55
  );
56
56
  }
57
- const firstImportIndex = ast.program.body.findIndex((node) => node.type === "ImportDeclaration");
58
- if (firstImportIndex !== -1) {
59
- ast.program.body.splice(firstImportIndex + 1, 0, ...imports);
57
+ const lastImportIndex = ast.program.body.findLastIndex((node) => node.type === "ImportDeclaration");
58
+ if (lastImportIndex !== -1) {
59
+ ast.program.body.splice(lastImportIndex + 1, 0, ...imports);
60
60
  } else {
61
61
  ast.program.body.unshift(...imports);
62
62
  }
63
63
  const i18nInitCode = needsBackwardCompatibility ? `// Before Grafana version 12.1.0 the plugin is responsible for loading translation resources
64
64
  // In Grafana version 12.1.0 and later Grafana is responsible for loading translation resources
65
- const loaders = semver.lt(config?.buildInfo?.version, '12.1.0') ? [loadResources] : [];
65
+ const loaders = semver.lt(config?.buildInfo?.version || '0.0.0', '12.1.0') ? [loadResources] : [];
66
66
 
67
67
  await initPluginTranslations(pluginJson.id, loaders);` : `await initPluginTranslations(pluginJson.id);`;
68
68
  const initAst = recast.parse(i18nInitCode, {
69
69
  parser: babelParser
70
70
  });
71
- const lastImportIndex = ast.program.body.findLastIndex((node) => node.type === "ImportDeclaration");
72
- if (lastImportIndex !== -1) {
73
- ast.program.body.splice(lastImportIndex + 1, 0, ...initAst.program.body);
71
+ const finalLastImportIndex = ast.program.body.findLastIndex((node) => node.type === "ImportDeclaration");
72
+ if (finalLastImportIndex !== -1) {
73
+ ast.program.body.splice(finalLastImportIndex + 1, 0, ...initAst.program.body);
74
74
  } else {
75
75
  ast.program.body.unshift(...initAst.program.body);
76
76
  }
@@ -100,7 +100,7 @@ function createLoadResourcesFile(context) {
100
100
  import pluginJson from 'plugin.json';
101
101
 
102
102
  const resources = LANGUAGES.reduce<Record<string, () => Promise<{ default: Resources }>>>((acc, lang) => {
103
- acc[lang.code] = async () => await import(\`./locales/\${lang.code}/\${pluginJson.id}.json\`);
103
+ acc[lang.code] = () => import(\`./locales/\${lang.code}/\${pluginJson.id}.json\`);
104
104
  return acc;
105
105
  }, {});
106
106
 
@@ -52,13 +52,15 @@ function updateEslintConfig(context) {
52
52
  });
53
53
  const imports = ast.program.body.filter((node) => node.type === "ImportDeclaration");
54
54
  const lastImport = imports[imports.length - 1];
55
+ const pluginImport = builders.importDeclaration(
56
+ [builders.importDefaultSpecifier(builders.identifier("grafanaI18nPlugin"))],
57
+ builders.literal("@grafana/i18n/eslint-plugin")
58
+ );
55
59
  if (lastImport) {
56
- const pluginImport = builders.importDeclaration(
57
- [builders.importDefaultSpecifier(builders.identifier("grafanaI18nPlugin"))],
58
- builders.literal("@grafana/i18n/eslint-plugin")
59
- );
60
60
  const lastImportIndex = ast.program.body.indexOf(lastImport);
61
61
  ast.program.body.splice(lastImportIndex + 1, 0, pluginImport);
62
+ } else {
63
+ ast.program.body.unshift(pluginImport);
62
64
  }
63
65
  recast.visit(ast, {
64
66
  visitCallExpression(path) {
@@ -31,11 +31,17 @@ Update your package.json to use "react": "^18.3.0" and "react-dom": "^18.3.0".`
31
31
  function checkNeedsBackwardCompatibility(context) {
32
32
  const pluginJsonRaw = context.getFile("src/plugin.json");
33
33
  if (!pluginJsonRaw) {
34
- return false;
34
+ return true;
35
35
  }
36
36
  try {
37
37
  const pluginJson = JSON.parse(pluginJsonRaw);
38
- const currentGrafanaDep = pluginJson.dependencies?.grafanaDependency || ">=11.0.0";
38
+ const currentGrafanaDep = pluginJson.dependencies?.grafanaDependency;
39
+ if (!currentGrafanaDep) {
40
+ additionsDebug(
41
+ "Warning: grafanaDependency is missing from plugin.json. Assuming backward compatibility mode is needed."
42
+ );
43
+ return true;
44
+ }
39
45
  const minVersion = coerce("12.1.0");
40
46
  const currentVersion = coerce(currentGrafanaDep.replace(/^[><=]+/, ""));
41
47
  if (currentVersion && minVersion && gte(currentVersion, minVersion)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafana/create-plugin",
3
- "version": "6.5.0-canary.2320.20267963205.0",
3
+ "version": "6.5.0-canary.2320.20268376971.0",
4
4
  "repository": {
5
5
  "directory": "packages/create-plugin",
6
6
  "url": "https://github.com/grafana/plugin-tools"
@@ -56,5 +56,5 @@
56
56
  "engines": {
57
57
  "node": ">=20"
58
58
  },
59
- "gitHead": "2d7dc3b835015e2b3c24f53907ad874b344446af"
59
+ "gitHead": "47d4c2ff4f55df3a644771982994d0c85ec7d96d"
60
60
  }
@@ -38,7 +38,7 @@ Additions are optional features that developers choose to add via `create-plugin
38
38
  ### Addition Behavior
39
39
 
40
40
  - Additions add new features or capabilities to a plugin (e.g., i18n support, testing frameworks, etc.)
41
- - it should be safe to run multiple times
41
+ - It should be safe to run multiple times
42
42
  - Always use defensive programming: check if features already exist before adding them
43
43
  - Use `additionsDebug()` for logging to help with troubleshooting
44
44
  - If the addition accepts user input, export a `schema` object using `valibot` for input validation
@@ -10,7 +10,7 @@ npx @grafana/create-plugin add i18n --locales <locales>
10
10
 
11
11
  ## Requirements
12
12
 
13
- - **Grafana >= 11.0.0**: i18n is not supported for Grafana versions prior to 11.0.0. If your plugin's `grafanaDependency` is set to a version < 11.0.0, the script will automatically update it to `>=11.0.0`.
13
+ - **Grafana >= 11.0.0**: i18n is not supported for Grafana versions prior to 11.0.0. If your plugin's `grafanaDependency` is set to a version < 11.0.0, the script will automatically update it to `>=11.0.0` (it will not exit with an error).
14
14
  - **React >= 18**: The `@grafana/i18n` package requires React 18 or higher. If your plugin uses React < 18, the script will exit with an error and prompt you to upgrade.
15
15
 
16
16
  ## Required Flags
@@ -73,10 +73,12 @@ export function addI18nInitialization(context: Context, needsBackwardCompatibili
73
73
  );
74
74
  }
75
75
 
76
- // Add imports after the first import statement
77
- const firstImportIndex = ast.program.body.findIndex((node: any) => node.type === 'ImportDeclaration');
78
- if (firstImportIndex !== -1) {
79
- ast.program.body.splice(firstImportIndex + 1, 0, ...imports);
76
+ // Find the last import index (use consistent approach for both imports and initialization)
77
+ const lastImportIndex = ast.program.body.findLastIndex((node: any) => node.type === 'ImportDeclaration');
78
+
79
+ // Add imports after the last import statement
80
+ if (lastImportIndex !== -1) {
81
+ ast.program.body.splice(lastImportIndex + 1, 0, ...imports);
80
82
  } else {
81
83
  ast.program.body.unshift(...imports);
82
84
  }
@@ -85,7 +87,7 @@ export function addI18nInitialization(context: Context, needsBackwardCompatibili
85
87
  const i18nInitCode = needsBackwardCompatibility
86
88
  ? `// Before Grafana version 12.1.0 the plugin is responsible for loading translation resources
87
89
  // In Grafana version 12.1.0 and later Grafana is responsible for loading translation resources
88
- const loaders = semver.lt(config?.buildInfo?.version, '12.1.0') ? [loadResources] : [];
90
+ const loaders = semver.lt(config?.buildInfo?.version || '0.0.0', '12.1.0') ? [loadResources] : [];
89
91
 
90
92
  await initPluginTranslations(pluginJson.id, loaders);`
91
93
  : `await initPluginTranslations(pluginJson.id);`;
@@ -95,10 +97,10 @@ await initPluginTranslations(pluginJson.id, loaders);`
95
97
  parser: babelParser,
96
98
  });
97
99
 
98
- // Find the last import index
99
- const lastImportIndex = ast.program.body.findLastIndex((node: any) => node.type === 'ImportDeclaration');
100
- if (lastImportIndex !== -1) {
101
- ast.program.body.splice(lastImportIndex + 1, 0, ...initAst.program.body);
100
+ // Find the last import index again (after adding new imports)
101
+ const finalLastImportIndex = ast.program.body.findLastIndex((node: any) => node.type === 'ImportDeclaration');
102
+ if (finalLastImportIndex !== -1) {
103
+ ast.program.body.splice(finalLastImportIndex + 1, 0, ...initAst.program.body);
102
104
  } else {
103
105
  ast.program.body.unshift(...initAst.program.body);
104
106
  }
@@ -135,7 +137,7 @@ export function createLoadResourcesFile(context: Context): void {
135
137
  import pluginJson from 'plugin.json';
136
138
 
137
139
  const resources = LANGUAGES.reduce<Record<string, () => Promise<{ default: Resources }>>>((acc, lang) => {
138
- acc[lang.code] = async () => await import(\`./locales/\${lang.code}/\${pluginJson.id}.json\`);
140
+ acc[lang.code] = () => import(\`./locales/\${lang.code}/\${pluginJson.id}.json\`);
139
141
  return acc;
140
142
  }, {});
141
143
 
@@ -73,14 +73,18 @@ export function updateEslintConfig(context: Context): void {
73
73
  const imports = ast.program.body.filter((node: any) => node.type === 'ImportDeclaration');
74
74
  const lastImport = imports[imports.length - 1];
75
75
 
76
- if (lastImport) {
77
- const pluginImport = builders.importDeclaration(
78
- [builders.importDefaultSpecifier(builders.identifier('grafanaI18nPlugin'))],
79
- builders.literal('@grafana/i18n/eslint-plugin')
80
- );
76
+ // Always create the plugin import
77
+ const pluginImport = builders.importDeclaration(
78
+ [builders.importDefaultSpecifier(builders.identifier('grafanaI18nPlugin'))],
79
+ builders.literal('@grafana/i18n/eslint-plugin')
80
+ );
81
81
 
82
+ if (lastImport) {
82
83
  const lastImportIndex = ast.program.body.indexOf(lastImport);
83
84
  ast.program.body.splice(lastImportIndex + 1, 0, pluginImport);
85
+ } else {
86
+ // No imports found, insert at the beginning
87
+ ast.program.body.unshift(pluginImport);
84
88
  }
85
89
 
86
90
  // Find the defineConfig array and add the plugin config
@@ -43,12 +43,21 @@ export function checkReactVersion(context: Context): void {
43
43
  export function checkNeedsBackwardCompatibility(context: Context): boolean {
44
44
  const pluginJsonRaw = context.getFile('src/plugin.json');
45
45
  if (!pluginJsonRaw) {
46
- return false;
46
+ // Default to backward compat for safety when plugin.json is missing
47
+ return true;
47
48
  }
48
49
 
49
50
  try {
50
51
  const pluginJson = JSON.parse(pluginJsonRaw);
51
- const currentGrafanaDep = pluginJson.dependencies?.grafanaDependency || '>=11.0.0';
52
+ const currentGrafanaDep = pluginJson.dependencies?.grafanaDependency;
53
+
54
+ if (!currentGrafanaDep) {
55
+ additionsDebug(
56
+ 'Warning: grafanaDependency is missing from plugin.json. Assuming backward compatibility mode is needed.'
57
+ );
58
+ return true;
59
+ }
60
+
52
61
  const minVersion = coerce('12.1.0');
53
62
  const currentVersion = coerce(currentGrafanaDep.replace(/^[><=]+/, ''));
54
63