@grafana/create-plugin 6.2.0-canary.2233.18644853669.0 → 6.2.0-canary.2233.18936261925.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 +64 -0
- package/dist/additions/manager.js +58 -1
- package/dist/additions/scripts/add-i18n.js +13 -1
- package/dist/commands/add.command.js +29 -35
- package/dist/constants.js +2 -10
- package/dist/utils/utils.config.js +6 -5
- package/dist/utils/utils.templates.js +7 -15
- package/dist/utils/utils.version.js +4 -10
- package/package.json +2 -2
- package/src/additions/additions.ts +1 -5
- package/src/additions/manager.ts +67 -0
- package/src/additions/scripts/add-i18n.ts +16 -0
- package/src/commands/add.command.ts +31 -42
- package/src/constants.ts +2 -10
- package/src/types.ts +0 -2
- package/src/utils/utils.config.ts +7 -6
- package/src/utils/utils.templates.ts +13 -22
- package/templates/common/_package.json +9 -13
- package/templates/common/npmrc +0 -3
- package/templates/github/workflows/bundle-stats.yml +1 -1
- package/templates/github/workflows/ci.yml +4 -4
- package/templates/github/workflows/cp-update.yml +1 -1
- package/templates/github/workflows/is-compatible.yml +1 -1
- package/templates/github/workflows/release.yml +1 -1
- package/dist/commands/add/prompts.js +0 -72
- package/src/commands/add/prompts.ts +0 -93
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
+
# v6.1.5 (Tue Oct 28 2025)
|
|
2
|
+
|
|
3
|
+
#### 🐛 Bug Fix
|
|
4
|
+
|
|
5
|
+
- Create Plugin: Include EOF newline when setting root config [#2246](https://github.com/grafana/plugin-tools/pull/2246) ([@MattIPv4](https://github.com/MattIPv4))
|
|
6
|
+
|
|
7
|
+
#### Authors: 1
|
|
8
|
+
|
|
9
|
+
- Matt Cowley ([@MattIPv4](https://github.com/MattIPv4))
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# v6.1.4 (Fri Oct 24 2025)
|
|
14
|
+
|
|
15
|
+
#### 🐛 Bug Fix
|
|
16
|
+
|
|
17
|
+
- Create Plugin: pin swc/core to 1.13.20 [#2243](https://github.com/grafana/plugin-tools/pull/2243) ([@jackw](https://github.com/jackw))
|
|
18
|
+
|
|
19
|
+
#### Authors: 1
|
|
20
|
+
|
|
21
|
+
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# v6.1.3 (Thu Oct 23 2025)
|
|
26
|
+
|
|
27
|
+
#### 🐛 Bug Fix
|
|
28
|
+
|
|
29
|
+
- Create Plugin: Scaffold workflows with versioned actions [#2234](https://github.com/grafana/plugin-tools/pull/2234) ([@jackw](https://github.com/jackw))
|
|
30
|
+
|
|
31
|
+
#### Authors: 1
|
|
32
|
+
|
|
33
|
+
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# v6.1.2 (Tue Oct 21 2025)
|
|
38
|
+
|
|
39
|
+
#### 🐛 Bug Fix
|
|
40
|
+
|
|
41
|
+
- Create Plugin: Remove cypress support [#2232](https://github.com/grafana/plugin-tools/pull/2232) ([@sunker](https://github.com/sunker))
|
|
42
|
+
- Update dependency @grafana/e2e-selectors to v12.2.0 [#2205](https://github.com/grafana/plugin-tools/pull/2205) ([@renovate[bot]](https://github.com/renovate[bot]) [@leventebalogh](https://github.com/leventebalogh) [@mckn](https://github.com/mckn))
|
|
43
|
+
|
|
44
|
+
#### Authors: 4
|
|
45
|
+
|
|
46
|
+
- [@renovate[bot]](https://github.com/renovate[bot])
|
|
47
|
+
- Erik Sundell ([@sunker](https://github.com/sunker))
|
|
48
|
+
- Levente Balogh ([@leventebalogh](https://github.com/leventebalogh))
|
|
49
|
+
- Marcus Andersson ([@mckn](https://github.com/mckn))
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
# v6.1.1 (Wed Oct 15 2025)
|
|
54
|
+
|
|
55
|
+
#### 🐛 Bug Fix
|
|
56
|
+
|
|
57
|
+
- Fix: Use proper install command for legacy plugin migrations [#2221](https://github.com/grafana/plugin-tools/pull/2221) ([@sunker]https://github.com/sunker))
|
|
58
|
+
|
|
59
|
+
#### Authors: 1
|
|
60
|
+
|
|
61
|
+
- Erik Sundell ([@sunker](https://github.com/sunker))
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
1
65
|
# v6.1.0 (Wed Oct 08 2025)
|
|
2
66
|
|
|
3
67
|
#### 🚀 Enhancement
|
|
@@ -11,6 +11,63 @@ function getAvailableAdditions(additions = defaultAdditions.additions) {
|
|
|
11
11
|
function getAdditionByName(name, additions = defaultAdditions.additions) {
|
|
12
12
|
return additions[name];
|
|
13
13
|
}
|
|
14
|
+
async function getAdditionFlags(addition) {
|
|
15
|
+
try {
|
|
16
|
+
const module = await import(addition.scriptPath);
|
|
17
|
+
return module.flags || [];
|
|
18
|
+
} catch (error) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function parseAdditionFlags(addition, argv) {
|
|
23
|
+
try {
|
|
24
|
+
const module = await import(addition.scriptPath);
|
|
25
|
+
if (module.parseFlags && typeof module.parseFlags === "function") {
|
|
26
|
+
return module.parseFlags(argv);
|
|
27
|
+
}
|
|
28
|
+
return {};
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function validateAdditionOptions(addition, options) {
|
|
34
|
+
const flags = await getAdditionFlags(addition);
|
|
35
|
+
if (!flags || flags.length === 0) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const missingFlags = [];
|
|
39
|
+
for (const flag of flags) {
|
|
40
|
+
if (flag.required) {
|
|
41
|
+
const value = options[flag.name];
|
|
42
|
+
if (value === void 0 || value === null || Array.isArray(value) && value.length === 0) {
|
|
43
|
+
missingFlags.push(flag.name);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (missingFlags.length > 0) {
|
|
48
|
+
const flagDocs = flags.filter((f) => missingFlags.includes(f.name)).map((f) => ` --${f.name}: ${f.description}`);
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Missing required flag${missingFlags.length > 1 ? "s" : ""}:
|
|
51
|
+
|
|
52
|
+
` + flagDocs.join("\n") + `
|
|
53
|
+
|
|
54
|
+
Example: npx @grafana/create-plugin add ${addition.name} --${missingFlags[0]}=value`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function runAdditionByName(additionName, argv, runOptions = {}) {
|
|
59
|
+
const addition = getAdditionByName(additionName);
|
|
60
|
+
if (!addition) {
|
|
61
|
+
const availableAdditions = getAvailableAdditions();
|
|
62
|
+
const additionsList = Object.keys(availableAdditions);
|
|
63
|
+
throw new Error(`Unknown addition: ${additionName}
|
|
64
|
+
|
|
65
|
+
Available additions: ${additionsList.join(", ")}`);
|
|
66
|
+
}
|
|
67
|
+
const options = await parseAdditionFlags(addition, argv);
|
|
68
|
+
await validateAdditionOptions(addition, options);
|
|
69
|
+
await runAddition(addition, options, runOptions);
|
|
70
|
+
}
|
|
14
71
|
async function runAddition(addition, additionOptions = {}, runOptions = {}) {
|
|
15
72
|
const basePath = process.cwd();
|
|
16
73
|
output.log({
|
|
@@ -45,4 +102,4 @@ async function executeAddition(addition, context, options = {}) {
|
|
|
45
102
|
return module.default(context, options);
|
|
46
103
|
}
|
|
47
104
|
|
|
48
|
-
export { executeAddition, getAdditionByName, getAvailableAdditions, runAddition };
|
|
105
|
+
export { executeAddition, getAdditionByName, getAdditionFlags, getAvailableAdditions, parseAdditionFlags, runAddition, runAdditionByName };
|
|
@@ -5,6 +5,18 @@ import { parseDocument, stringify } from 'yaml';
|
|
|
5
5
|
import { addDependenciesToPackageJson } from '../../migrations/utils.js';
|
|
6
6
|
|
|
7
7
|
const { builders } = recast.types;
|
|
8
|
+
const flags = [
|
|
9
|
+
{
|
|
10
|
+
name: "locales",
|
|
11
|
+
description: "Comma-separated list of locales (e.g., en-US,es-ES)",
|
|
12
|
+
required: true
|
|
13
|
+
}
|
|
14
|
+
];
|
|
15
|
+
function parseFlags(argv) {
|
|
16
|
+
return {
|
|
17
|
+
locales: argv.locales ? argv.locales.split(",").map((l) => l.trim()) : []
|
|
18
|
+
};
|
|
19
|
+
}
|
|
8
20
|
function migrate(context, options = { locales: ["en-US"] }) {
|
|
9
21
|
const { locales } = options;
|
|
10
22
|
additionsDebug("Adding i18n support with locales:", locales);
|
|
@@ -430,4 +442,4 @@ export const loadResources: ResourceLoader = async (resolvedLanguage: string) =>
|
|
|
430
442
|
additionsDebug("Created src/loadResources.ts for backward compatibility");
|
|
431
443
|
}
|
|
432
444
|
|
|
433
|
-
export { migrate as default };
|
|
445
|
+
export { migrate as default, flags, parseFlags };
|
|
@@ -1,49 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { runAdditionByName, getAvailableAdditions, getAdditionFlags } from '../additions/manager.js';
|
|
2
2
|
import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
|
|
3
3
|
import { isPluginDirectory } from '../utils/utils.plugin.js';
|
|
4
4
|
import { output } from '../utils/utils.console.js';
|
|
5
|
-
import { promptI18nOptions } from './add/prompts.js';
|
|
6
5
|
|
|
7
6
|
const add = async (argv) => {
|
|
8
7
|
const subCommand = argv._[1];
|
|
9
8
|
if (!subCommand) {
|
|
10
|
-
|
|
11
|
-
const additionsList = Object.values(availableAdditions).map(
|
|
12
|
-
(addition2) => `${addition2.name} - ${addition2.description}`
|
|
13
|
-
);
|
|
14
|
-
output.error({
|
|
15
|
-
title: "No addition specified",
|
|
16
|
-
body: [
|
|
17
|
-
"Usage: npx @grafana/create-plugin add <addition-name>",
|
|
18
|
-
"",
|
|
19
|
-
"Available additions:",
|
|
20
|
-
...output.bulletList(additionsList)
|
|
21
|
-
]
|
|
22
|
-
});
|
|
9
|
+
await showAdditionsHelp();
|
|
23
10
|
process.exit(1);
|
|
24
11
|
}
|
|
25
12
|
await performPreAddChecks(argv);
|
|
26
|
-
const addition = getAdditionByName(subCommand);
|
|
27
|
-
if (!addition) {
|
|
28
|
-
const availableAdditions = getAvailableAdditions();
|
|
29
|
-
const additionsList = Object.values(availableAdditions).map((addition2) => addition2.name);
|
|
30
|
-
output.error({
|
|
31
|
-
title: `Unknown addition: ${subCommand}`,
|
|
32
|
-
body: ["Available additions:", ...output.bulletList(additionsList)]
|
|
33
|
-
});
|
|
34
|
-
process.exit(1);
|
|
35
|
-
}
|
|
36
13
|
try {
|
|
37
|
-
|
|
38
|
-
switch (addition.name) {
|
|
39
|
-
case "i18n":
|
|
40
|
-
options = await promptI18nOptions();
|
|
41
|
-
break;
|
|
42
|
-
default:
|
|
43
|
-
break;
|
|
44
|
-
}
|
|
45
|
-
const commitChanges = argv.commit;
|
|
46
|
-
await runAddition(addition, options, { commitChanges });
|
|
14
|
+
await runAdditionByName(subCommand, argv, { commitChanges: argv.commit });
|
|
47
15
|
} catch (error) {
|
|
48
16
|
if (error instanceof Error) {
|
|
49
17
|
output.error({
|
|
@@ -54,6 +22,32 @@ const add = async (argv) => {
|
|
|
54
22
|
process.exit(1);
|
|
55
23
|
}
|
|
56
24
|
};
|
|
25
|
+
async function showAdditionsHelp() {
|
|
26
|
+
const availableAdditions = getAvailableAdditions();
|
|
27
|
+
const additionsList = await Promise.all(
|
|
28
|
+
Object.values(availableAdditions).map(async (addition) => {
|
|
29
|
+
let info = `${addition.name} - ${addition.description}`;
|
|
30
|
+
const flags = await getAdditionFlags(addition);
|
|
31
|
+
if (flags.length > 0) {
|
|
32
|
+
const flagDocs = flags.map((flag) => {
|
|
33
|
+
const req = flag.required ? " (required)" : " (optional)";
|
|
34
|
+
return ` --${flag.name}: ${flag.description}${req}`;
|
|
35
|
+
});
|
|
36
|
+
info += "\n" + flagDocs.join("\n");
|
|
37
|
+
}
|
|
38
|
+
return info;
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
output.error({
|
|
42
|
+
title: "No addition specified",
|
|
43
|
+
body: [
|
|
44
|
+
"Usage: npx @grafana/create-plugin add <addition-name> [options]",
|
|
45
|
+
"",
|
|
46
|
+
"Available additions:",
|
|
47
|
+
...output.bulletList(additionsList)
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
}
|
|
57
51
|
async function performPreAddChecks(argv) {
|
|
58
52
|
if (!await isGitDirectory() && !argv.force) {
|
|
59
53
|
output.error({
|
package/dist/constants.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
|
|
4
4
|
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
5
5
|
const IS_DEV = process.env.CREATE_PLUGIN_DEV !== void 0;
|
|
@@ -32,18 +32,10 @@ const EXTRA_TEMPLATE_VARIABLES = {
|
|
|
32
32
|
const DEFAULT_FEATURE_FLAGS = {
|
|
33
33
|
useReactRouterV6: true,
|
|
34
34
|
bundleGrafanaUI: false,
|
|
35
|
-
usePlaywright: true,
|
|
36
35
|
useExperimentalRspack: false,
|
|
37
36
|
useExperimentalUpdates: true
|
|
38
37
|
};
|
|
39
|
-
const GRAFANA_FE_PACKAGES = [
|
|
40
|
-
"@grafana/data",
|
|
41
|
-
"@grafana/e2e-selectors",
|
|
42
|
-
"@grafana/e2e",
|
|
43
|
-
"@grafana/runtime",
|
|
44
|
-
"@grafana/schema",
|
|
45
|
-
"@grafana/ui"
|
|
46
|
-
];
|
|
38
|
+
const GRAFANA_FE_PACKAGES = ["@grafana/data", "@grafana/runtime", "@grafana/schema", "@grafana/ui"];
|
|
47
39
|
const MIGRATION_CONFIG = {
|
|
48
40
|
// Files that should be overriden during a migration.
|
|
49
41
|
// (paths are relative to the scaffolded projects root)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { CURRENT_APP_VERSION } from './utils.version.js';
|
|
5
1
|
import { argv, commandName } from './utils.cli.js';
|
|
2
|
+
import { CURRENT_APP_VERSION } from './utils.version.js';
|
|
6
3
|
import { DEFAULT_FEATURE_FLAGS } from '../constants.js';
|
|
4
|
+
import fs from 'node:fs';
|
|
7
5
|
import { output } from './utils.console.js';
|
|
8
6
|
import { partitionArr } from './utils.helpers.js';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { writeFile } from 'node:fs/promises';
|
|
9
|
+
import { EOL } from 'node:os';
|
|
9
10
|
|
|
10
11
|
let hasShownConfigWarnings = false;
|
|
11
12
|
function getConfig(workDir = process.cwd()) {
|
|
@@ -88,7 +89,7 @@ async function setRootConfig(configOverride = {}) {
|
|
|
88
89
|
const rootConfig = getRootConfig();
|
|
89
90
|
const rootConfigPath = path.resolve(process.cwd(), ".config/.cprc.json");
|
|
90
91
|
const updatedConfig = { ...rootConfig, ...configOverride };
|
|
91
|
-
await writeFile(rootConfigPath, JSON.stringify(updatedConfig, null, 2));
|
|
92
|
+
await writeFile(rootConfigPath, JSON.stringify(updatedConfig, null, 2) + EOL);
|
|
92
93
|
return updatedConfig;
|
|
93
94
|
}
|
|
94
95
|
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { glob } from 'glob';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import fs from 'node:fs';
|
|
1
|
+
import { DEFAULT_FEATURE_FLAGS, EXTRA_TEMPLATE_VARIABLES, PLUGIN_TYPES, TEMPLATE_PATHS, EXPORT_PATH_PREFIX } from '../constants.js';
|
|
5
2
|
import { isFile, getExportFileName, filterOutCommonFiles, isFileStartingWith } from './utils.files.js';
|
|
3
|
+
import { getPackageManagerFromUserAgent, getPackageManagerInstallCmd, getPackageManagerWithFallback } from './utils.packageManager.js';
|
|
6
4
|
import { normalizeId, renderHandlebarsTemplate } from './utils.handlebars.js';
|
|
7
|
-
import {
|
|
5
|
+
import { CURRENT_APP_VERSION } from './utils.version.js';
|
|
8
6
|
import { debug } from './utils.cli.js';
|
|
9
|
-
import
|
|
10
|
-
import { getPackageManagerFromUserAgent, getPackageManagerInstallCmd, getPackageManagerWithFallback } from './utils.packageManager.js';
|
|
11
|
-
import { getGrafanaRuntimeVersion, CURRENT_APP_VERSION } from './utils.version.js';
|
|
7
|
+
import fs from 'node:fs';
|
|
12
8
|
import { getConfig } from './utils.config.js';
|
|
9
|
+
import { getPluginJson } from './utils.plugin.js';
|
|
10
|
+
import { glob } from 'glob';
|
|
11
|
+
import path from 'node:path';
|
|
13
12
|
|
|
14
13
|
const templatesDebugger = debug.extend("templates");
|
|
15
14
|
function getTemplateFiles(pluginType, filter) {
|
|
@@ -57,9 +56,6 @@ function renderTemplateFromFile(templateFile, data) {
|
|
|
57
56
|
function getTemplateData(cliArgs) {
|
|
58
57
|
const { features } = getConfig();
|
|
59
58
|
const currentVersion = CURRENT_APP_VERSION;
|
|
60
|
-
const grafanaVersion = getGrafanaRuntimeVersion();
|
|
61
|
-
const usePlaywright = features.usePlaywright === true || isFile(path.join(process.cwd(), "playwright.config.ts"));
|
|
62
|
-
const useCypress = !usePlaywright && lt(grafanaVersion, "11.0.0") && fs.existsSync(path.join(process.cwd(), "cypress"));
|
|
63
59
|
const bundleGrafanaUI = features.bundleGrafanaUI ?? DEFAULT_FEATURE_FLAGS.bundleGrafanaUI;
|
|
64
60
|
const getReactRouterVersion = () => features.useReactRouterV6 ? "6.22.0" : "5.2.0";
|
|
65
61
|
const isAppType = (pluginType) => pluginType === PLUGIN_TYPES.app || pluginType === PLUGIN_TYPES.scenes;
|
|
@@ -86,8 +82,6 @@ function getTemplateData(cliArgs) {
|
|
|
86
82
|
useReactRouterV6: features.useReactRouterV6 ?? DEFAULT_FEATURE_FLAGS.useReactRouterV6,
|
|
87
83
|
reactRouterVersion: getReactRouterVersion(),
|
|
88
84
|
scenesVersion: features.useReactRouterV6 ? "^6.10.4" : "^5.41.3",
|
|
89
|
-
usePlaywright,
|
|
90
|
-
useCypress,
|
|
91
85
|
useExperimentalRspack: Boolean(features.useExperimentalRspack),
|
|
92
86
|
frontendBundler
|
|
93
87
|
};
|
|
@@ -111,8 +105,6 @@ function getTemplateData(cliArgs) {
|
|
|
111
105
|
useReactRouterV6: features.useReactRouterV6 ?? DEFAULT_FEATURE_FLAGS.useReactRouterV6,
|
|
112
106
|
reactRouterVersion: getReactRouterVersion(),
|
|
113
107
|
scenesVersion: features.useReactRouterV6 ? "^6.10.4" : "^5.41.3",
|
|
114
|
-
usePlaywright,
|
|
115
|
-
useCypress,
|
|
116
108
|
pluginExecutable: pluginJson.executable,
|
|
117
109
|
useExperimentalRspack: Boolean(features.useExperimentalRspack),
|
|
118
110
|
frontendBundler
|
|
@@ -1,14 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import 'node:fs';
|
|
2
|
+
import 'node:path';
|
|
3
3
|
import { getVersion } from '../libs/version/src/index.js';
|
|
4
|
-
import
|
|
4
|
+
import '../constants.js';
|
|
5
5
|
|
|
6
6
|
const CURRENT_APP_VERSION = getVersion();
|
|
7
|
-
function getGrafanaRuntimeVersion() {
|
|
8
|
-
const packageJsonPath = path.join(TEMPLATE_PATHS.common, "_package.json");
|
|
9
|
-
const pkg = readFileSync(packageJsonPath, "utf8");
|
|
10
|
-
const { version } = /\"(@grafana\/runtime)\":\s\"\^(?<version>.*)\"/.exec(pkg)?.groups ?? {};
|
|
11
|
-
return version;
|
|
12
|
-
}
|
|
13
7
|
|
|
14
|
-
export { CURRENT_APP_VERSION
|
|
8
|
+
export { CURRENT_APP_VERSION };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafana/create-plugin",
|
|
3
|
-
"version": "6.2.0-canary.2233.
|
|
3
|
+
"version": "6.2.0-canary.2233.18936261925.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"directory": "packages/create-plugin",
|
|
6
6
|
"url": "https://github.com/grafana/plugin-tools"
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": ">=20"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "4fe983e6dd98bd64f3cb807b5a44906de0ec8603"
|
|
65
65
|
}
|
|
@@ -4,10 +4,6 @@ export type AdditionMeta = {
|
|
|
4
4
|
scriptPath: string;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
type Additions = {
|
|
8
|
-
additions: Record<string, AdditionMeta>;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
7
|
export default {
|
|
12
8
|
additions: {
|
|
13
9
|
i18n: {
|
|
@@ -16,4 +12,4 @@ export default {
|
|
|
16
12
|
scriptPath: './scripts/add-i18n.js',
|
|
17
13
|
},
|
|
18
14
|
},
|
|
19
|
-
}
|
|
15
|
+
};
|
package/src/additions/manager.ts
CHANGED
|
@@ -26,6 +26,73 @@ export function getAdditionByName(
|
|
|
26
26
|
return additions[name];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
export async function getAdditionFlags(addition: AdditionMeta): Promise<any[]> {
|
|
30
|
+
try {
|
|
31
|
+
const module = await import(addition.scriptPath);
|
|
32
|
+
return module.flags || [];
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function parseAdditionFlags(addition: AdditionMeta, argv: any): Promise<AdditionOptions> {
|
|
39
|
+
try {
|
|
40
|
+
const module = await import(addition.scriptPath);
|
|
41
|
+
if (module.parseFlags && typeof module.parseFlags === 'function') {
|
|
42
|
+
return module.parseFlags(argv);
|
|
43
|
+
}
|
|
44
|
+
return {};
|
|
45
|
+
} catch (error) {
|
|
46
|
+
return {};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function validateAdditionOptions(addition: AdditionMeta, options: AdditionOptions): Promise<void> {
|
|
51
|
+
const flags = await getAdditionFlags(addition);
|
|
52
|
+
|
|
53
|
+
if (!flags || flags.length === 0) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const missingFlags: string[] = [];
|
|
58
|
+
|
|
59
|
+
for (const flag of flags) {
|
|
60
|
+
if (flag.required) {
|
|
61
|
+
const value = options[flag.name];
|
|
62
|
+
if (value === undefined || value === null || (Array.isArray(value) && value.length === 0)) {
|
|
63
|
+
missingFlags.push(flag.name);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (missingFlags.length > 0) {
|
|
69
|
+
const flagDocs = flags.filter((f) => missingFlags.includes(f.name)).map((f) => ` --${f.name}: ${f.description}`);
|
|
70
|
+
|
|
71
|
+
throw new Error(
|
|
72
|
+
`Missing required flag${missingFlags.length > 1 ? 's' : ''}:\n\n` +
|
|
73
|
+
flagDocs.join('\n') +
|
|
74
|
+
`\n\nExample: npx @grafana/create-plugin add ${addition.name} --${missingFlags[0]}=value`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function runAdditionByName(
|
|
80
|
+
additionName: string,
|
|
81
|
+
argv: any,
|
|
82
|
+
runOptions: RunAdditionOptions = {}
|
|
83
|
+
): Promise<void> {
|
|
84
|
+
const addition = getAdditionByName(additionName);
|
|
85
|
+
if (!addition) {
|
|
86
|
+
const availableAdditions = getAvailableAdditions();
|
|
87
|
+
const additionsList = Object.keys(availableAdditions);
|
|
88
|
+
throw new Error(`Unknown addition: ${additionName}\n\nAvailable additions: ${additionsList.join(', ')}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const options = await parseAdditionFlags(addition, argv);
|
|
92
|
+
await validateAdditionOptions(addition, options);
|
|
93
|
+
await runAddition(addition, options, runOptions);
|
|
94
|
+
}
|
|
95
|
+
|
|
29
96
|
export async function runAddition(
|
|
30
97
|
addition: AdditionMeta,
|
|
31
98
|
additionOptions: AdditionOptions = {},
|
|
@@ -12,6 +12,22 @@ export type I18nOptions = {
|
|
|
12
12
|
locales: string[];
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
// Flag schema for CLI
|
|
16
|
+
export const flags = [
|
|
17
|
+
{
|
|
18
|
+
name: 'locales',
|
|
19
|
+
description: 'Comma-separated list of locales (e.g., en-US,es-ES)',
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
// Parse CLI flags to options
|
|
25
|
+
export function parseFlags(argv: any): I18nOptions {
|
|
26
|
+
return {
|
|
27
|
+
locales: argv.locales ? argv.locales.split(',').map((l: string) => l.trim()) : [],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
export default function migrate(context: Context, options: I18nOptions = { locales: ['en-US'] }): Context {
|
|
16
32
|
const { locales } = options;
|
|
17
33
|
|
|
@@ -1,61 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getAdditionFlags, getAvailableAdditions, runAdditionByName } from '../additions/manager.js';
|
|
2
2
|
import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
|
|
3
3
|
|
|
4
4
|
import { isPluginDirectory } from '../utils/utils.plugin.js';
|
|
5
5
|
import minimist from 'minimist';
|
|
6
6
|
import { output } from '../utils/utils.console.js';
|
|
7
|
-
import { promptI18nOptions } from './add/prompts.js';
|
|
8
7
|
|
|
9
8
|
export const add = async (argv: minimist.ParsedArgs) => {
|
|
10
9
|
const subCommand = argv._[1];
|
|
11
10
|
|
|
12
11
|
if (!subCommand) {
|
|
13
|
-
|
|
14
|
-
const additionsList = Object.values(availableAdditions).map(
|
|
15
|
-
(addition) => `${addition.name} - ${addition.description}`
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
output.error({
|
|
19
|
-
title: 'No addition specified',
|
|
20
|
-
body: [
|
|
21
|
-
'Usage: npx @grafana/create-plugin add <addition-name>',
|
|
22
|
-
'',
|
|
23
|
-
'Available additions:',
|
|
24
|
-
...output.bulletList(additionsList),
|
|
25
|
-
],
|
|
26
|
-
});
|
|
12
|
+
await showAdditionsHelp();
|
|
27
13
|
process.exit(1);
|
|
28
14
|
}
|
|
29
15
|
|
|
30
16
|
await performPreAddChecks(argv);
|
|
31
17
|
|
|
32
|
-
const addition = getAdditionByName(subCommand);
|
|
33
|
-
|
|
34
|
-
if (!addition) {
|
|
35
|
-
const availableAdditions = getAvailableAdditions();
|
|
36
|
-
const additionsList = Object.values(availableAdditions).map((addition) => addition.name);
|
|
37
|
-
|
|
38
|
-
output.error({
|
|
39
|
-
title: `Unknown addition: ${subCommand}`,
|
|
40
|
-
body: ['Available additions:', ...output.bulletList(additionsList)],
|
|
41
|
-
});
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
18
|
try {
|
|
46
|
-
|
|
47
|
-
let options = {};
|
|
48
|
-
|
|
49
|
-
switch (addition.name) {
|
|
50
|
-
case 'i18n':
|
|
51
|
-
options = await promptI18nOptions();
|
|
52
|
-
break;
|
|
53
|
-
default:
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const commitChanges = argv.commit;
|
|
58
|
-
await runAddition(addition, options, { commitChanges });
|
|
19
|
+
await runAdditionByName(subCommand, argv, { commitChanges: argv.commit });
|
|
59
20
|
} catch (error) {
|
|
60
21
|
if (error instanceof Error) {
|
|
61
22
|
output.error({
|
|
@@ -67,6 +28,34 @@ export const add = async (argv: minimist.ParsedArgs) => {
|
|
|
67
28
|
}
|
|
68
29
|
};
|
|
69
30
|
|
|
31
|
+
async function showAdditionsHelp() {
|
|
32
|
+
const availableAdditions = getAvailableAdditions();
|
|
33
|
+
const additionsList = await Promise.all(
|
|
34
|
+
Object.values(availableAdditions).map(async (addition) => {
|
|
35
|
+
let info = `${addition.name} - ${addition.description}`;
|
|
36
|
+
const flags = await getAdditionFlags(addition);
|
|
37
|
+
if (flags.length > 0) {
|
|
38
|
+
const flagDocs = flags.map((flag) => {
|
|
39
|
+
const req = flag.required ? ' (required)' : ' (optional)';
|
|
40
|
+
return ` --${flag.name}: ${flag.description}${req}`;
|
|
41
|
+
});
|
|
42
|
+
info += '\n' + flagDocs.join('\n');
|
|
43
|
+
}
|
|
44
|
+
return info;
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
output.error({
|
|
49
|
+
title: 'No addition specified',
|
|
50
|
+
body: [
|
|
51
|
+
'Usage: npx @grafana/create-plugin add <addition-name> [options]',
|
|
52
|
+
'',
|
|
53
|
+
'Available additions:',
|
|
54
|
+
...output.bulletList(additionsList),
|
|
55
|
+
],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
70
59
|
async function performPreAddChecks(argv: minimist.ParsedArgs) {
|
|
71
60
|
if (!(await isGitDirectory()) && !argv.force) {
|
|
72
61
|
output.error({
|
package/src/constants.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import path from 'node:path';
|
|
3
3
|
|
|
4
4
|
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
5
5
|
|
|
@@ -51,19 +51,11 @@ export const EXTRA_TEMPLATE_VARIABLES = {
|
|
|
51
51
|
export const DEFAULT_FEATURE_FLAGS = {
|
|
52
52
|
useReactRouterV6: true,
|
|
53
53
|
bundleGrafanaUI: false,
|
|
54
|
-
usePlaywright: true,
|
|
55
54
|
useExperimentalRspack: false,
|
|
56
55
|
useExperimentalUpdates: true,
|
|
57
56
|
};
|
|
58
57
|
|
|
59
|
-
export const GRAFANA_FE_PACKAGES = [
|
|
60
|
-
'@grafana/data',
|
|
61
|
-
'@grafana/e2e-selectors',
|
|
62
|
-
'@grafana/e2e',
|
|
63
|
-
'@grafana/runtime',
|
|
64
|
-
'@grafana/schema',
|
|
65
|
-
'@grafana/ui',
|
|
66
|
-
];
|
|
58
|
+
export const GRAFANA_FE_PACKAGES = ['@grafana/data', '@grafana/runtime', '@grafana/schema', '@grafana/ui'];
|
|
67
59
|
|
|
68
60
|
export const MIGRATION_CONFIG = {
|
|
69
61
|
// Files that should be overriden during a migration.
|
package/src/types.ts
CHANGED
|
@@ -25,8 +25,6 @@ export type TemplateData = {
|
|
|
25
25
|
useReactRouterV6: boolean;
|
|
26
26
|
scenesVersion: string;
|
|
27
27
|
reactRouterVersion: string;
|
|
28
|
-
usePlaywright: boolean;
|
|
29
|
-
useCypress: boolean;
|
|
30
28
|
useExperimentalRspack: boolean;
|
|
31
29
|
pluginExecutable?: string;
|
|
32
30
|
frontendBundler: 'webpack' | 'rspack';
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import { writeFile } from 'node:fs/promises';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { CURRENT_APP_VERSION } from './utils.version.js';
|
|
5
1
|
import { argv, commandName } from './utils.cli.js';
|
|
2
|
+
|
|
3
|
+
import { CURRENT_APP_VERSION } from './utils.version.js';
|
|
6
4
|
import { DEFAULT_FEATURE_FLAGS } from '../constants.js';
|
|
5
|
+
import fs from 'node:fs';
|
|
7
6
|
import { output } from './utils.console.js';
|
|
8
7
|
import { partitionArr } from './utils.helpers.js';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { writeFile } from 'node:fs/promises';
|
|
10
|
+
import { EOL } from 'node:os';
|
|
9
11
|
|
|
10
12
|
export type FeatureFlags = {
|
|
11
13
|
bundleGrafanaUI?: boolean;
|
|
@@ -13,7 +15,6 @@ export type FeatureFlags = {
|
|
|
13
15
|
// If set to true, the plugin will be scaffolded with React Router v6. Defaults to true.
|
|
14
16
|
// (Attention! We always scaffold new projects with React Router v6, so if you are changing this to `false` manually you will need to make changes to the React code as well.)
|
|
15
17
|
useReactRouterV6?: boolean;
|
|
16
|
-
usePlaywright?: boolean;
|
|
17
18
|
useExperimentalRspack?: boolean;
|
|
18
19
|
useExperimentalUpdates?: boolean;
|
|
19
20
|
};
|
|
@@ -127,7 +128,7 @@ export async function setRootConfig(configOverride: Partial<CreatePluginConfig>
|
|
|
127
128
|
const rootConfigPath = path.resolve(process.cwd(), '.config/.cprc.json');
|
|
128
129
|
const updatedConfig = { ...rootConfig, ...configOverride };
|
|
129
130
|
|
|
130
|
-
await writeFile(rootConfigPath, JSON.stringify(updatedConfig, null, 2));
|
|
131
|
+
await writeFile(rootConfigPath, JSON.stringify(updatedConfig, null, 2) + EOL);
|
|
131
132
|
|
|
132
133
|
return updatedConfig;
|
|
133
134
|
}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import { lt as semverLt } from 'semver';
|
|
2
|
-
import { glob } from 'glob';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import fs from 'node:fs';
|
|
5
|
-
import { filterOutCommonFiles, isFile, isFileStartingWith } from './utils.files.js';
|
|
6
|
-
import { normalizeId, renderHandlebarsTemplate } from './utils.handlebars.js';
|
|
7
|
-
import { getPluginJson } from './utils.plugin.js';
|
|
8
|
-
import { debug } from './utils.cli.js';
|
|
9
1
|
import {
|
|
10
|
-
|
|
2
|
+
DEFAULT_FEATURE_FLAGS,
|
|
11
3
|
EXPORT_PATH_PREFIX,
|
|
12
4
|
EXTRA_TEMPLATE_VARIABLES,
|
|
13
5
|
PLUGIN_TYPES,
|
|
14
|
-
|
|
6
|
+
TEMPLATE_PATHS,
|
|
15
7
|
} from '../constants.js';
|
|
16
8
|
import { GenerateCliArgs, TemplateData } from '../types.js';
|
|
9
|
+
import { filterOutCommonFiles, isFile, isFileStartingWith } from './utils.files.js';
|
|
17
10
|
import {
|
|
11
|
+
getPackageManagerFromUserAgent,
|
|
18
12
|
getPackageManagerInstallCmd,
|
|
19
13
|
getPackageManagerWithFallback,
|
|
20
|
-
getPackageManagerFromUserAgent,
|
|
21
14
|
} from './utils.packageManager.js';
|
|
22
|
-
import {
|
|
23
|
-
|
|
15
|
+
import { normalizeId, renderHandlebarsTemplate } from './utils.handlebars.js';
|
|
16
|
+
|
|
17
|
+
import { CURRENT_APP_VERSION } from './utils.version.js';
|
|
18
|
+
import { debug } from './utils.cli.js';
|
|
19
|
+
import fs from 'node:fs';
|
|
24
20
|
import { getConfig } from './utils.config.js';
|
|
21
|
+
import { getExportFileName } from '../utils/utils.files.js';
|
|
22
|
+
import { getPluginJson } from './utils.plugin.js';
|
|
23
|
+
import { glob } from 'glob';
|
|
24
|
+
import path from 'node:path';
|
|
25
25
|
|
|
26
26
|
const templatesDebugger = debug.extend('templates');
|
|
27
27
|
|
|
@@ -95,11 +95,6 @@ export function renderTemplateFromFile(templateFile: string, data?: any) {
|
|
|
95
95
|
export function getTemplateData(cliArgs?: GenerateCliArgs): TemplateData {
|
|
96
96
|
const { features } = getConfig();
|
|
97
97
|
const currentVersion = CURRENT_APP_VERSION;
|
|
98
|
-
const grafanaVersion = getGrafanaRuntimeVersion();
|
|
99
|
-
const usePlaywright = features.usePlaywright === true || isFile(path.join(process.cwd(), 'playwright.config.ts'));
|
|
100
|
-
//@grafana/e2e was deprecated in Grafana 11
|
|
101
|
-
const useCypress =
|
|
102
|
-
!usePlaywright && semverLt(grafanaVersion, '11.0.0') && fs.existsSync(path.join(process.cwd(), 'cypress'));
|
|
103
98
|
const bundleGrafanaUI = features.bundleGrafanaUI ?? DEFAULT_FEATURE_FLAGS.bundleGrafanaUI;
|
|
104
99
|
const getReactRouterVersion = () => (features.useReactRouterV6 ? '6.22.0' : '5.2.0');
|
|
105
100
|
const isAppType = (pluginType: string) => pluginType === PLUGIN_TYPES.app || pluginType === PLUGIN_TYPES.scenes;
|
|
@@ -130,8 +125,6 @@ export function getTemplateData(cliArgs?: GenerateCliArgs): TemplateData {
|
|
|
130
125
|
useReactRouterV6: features.useReactRouterV6 ?? DEFAULT_FEATURE_FLAGS.useReactRouterV6,
|
|
131
126
|
reactRouterVersion: getReactRouterVersion(),
|
|
132
127
|
scenesVersion: features.useReactRouterV6 ? '^6.10.4' : '^5.41.3',
|
|
133
|
-
usePlaywright,
|
|
134
|
-
useCypress,
|
|
135
128
|
useExperimentalRspack: Boolean(features.useExperimentalRspack),
|
|
136
129
|
frontendBundler,
|
|
137
130
|
};
|
|
@@ -158,8 +151,6 @@ export function getTemplateData(cliArgs?: GenerateCliArgs): TemplateData {
|
|
|
158
151
|
useReactRouterV6: features.useReactRouterV6 ?? DEFAULT_FEATURE_FLAGS.useReactRouterV6,
|
|
159
152
|
reactRouterVersion: getReactRouterVersion(),
|
|
160
153
|
scenesVersion: features.useReactRouterV6 ? '^6.10.4' : '^5.41.3',
|
|
161
|
-
usePlaywright,
|
|
162
|
-
useCypress,
|
|
163
154
|
pluginExecutable: pluginJson.executable,
|
|
164
155
|
useExperimentalRspack: Boolean(features.useExperimentalRspack),
|
|
165
156
|
frontendBundler,
|
|
@@ -8,26 +8,22 @@
|
|
|
8
8
|
"test:ci": "jest --passWithNoTests --maxWorkers 4",
|
|
9
9
|
"typecheck": "tsc --noEmit",
|
|
10
10
|
"lint": "eslint --cache .",
|
|
11
|
-
"lint:fix": "{{ packageManagerName }} run lint{{#if isNPM}} --{{/if}} --fix && prettier --write --list-different .",
|
|
12
|
-
"e2e": "playwright test",
|
|
13
|
-
"e2e": "{{ packageManagerName }} exec cypress install && {{ packageManagerName }} exec grafana-e2e run",
|
|
14
|
-
"e2e:update": "{{ packageManagerName }} exec cypress install && {{ packageManagerName }} exec grafana-e2e run --update-screenshots",{{/if}}
|
|
11
|
+
"lint:fix": "{{ packageManagerName }} run lint{{#if isNPM}} --{{/if}} --fix && prettier --write --list-different .",
|
|
12
|
+
"e2e": "playwright test",
|
|
15
13
|
"server": "docker compose up --build",
|
|
16
14
|
"sign": "npx --yes @grafana/sign-plugin@latest"
|
|
17
15
|
},
|
|
18
16
|
"author": "{{ sentenceCase orgName }}",
|
|
19
17
|
"license": "Apache-2.0",
|
|
20
18
|
"devDependencies": {
|
|
21
|
-
|
|
22
|
-
"@grafana/e2e
|
|
23
|
-
"@grafana/
|
|
24
|
-
"@
|
|
25
|
-
"@grafana/tsconfig": "^2.0.0",{{#if usePlaywright}}
|
|
26
|
-
"@playwright/test": "^1.52.0",{{/if}}{{#if useExperimentalRspack}}
|
|
19
|
+
"@grafana/eslint-config": "^8.2.0",
|
|
20
|
+
"@grafana/plugin-e2e": "^2.2.0",
|
|
21
|
+
"@grafana/tsconfig": "^2.0.0",
|
|
22
|
+
"@playwright/test": "^1.52.0",{{#if useExperimentalRspack}}
|
|
27
23
|
"@rspack/core": "^1.3.0",
|
|
28
24
|
"@rspack/cli": "^1.3.0",{{/if}}
|
|
29
25
|
"@stylistic/eslint-plugin-ts": "^2.9.0",
|
|
30
|
-
"@swc/core": "
|
|
26
|
+
"@swc/core": "1.13.20",
|
|
31
27
|
"@swc/helpers": "^0.5.0",
|
|
32
28
|
"@swc/jest": "^0.2.26",
|
|
33
29
|
"@testing-library/jest-dom": "6.1.4",
|
|
@@ -56,8 +52,8 @@
|
|
|
56
52
|
"replace-in-file-webpack-plugin": "^1.0.6",{{#if useExperimentalRspack}}
|
|
57
53
|
"rspack-plugin-virtual-module": "^0.1.13",{{/if}}
|
|
58
54
|
"sass": "1.63.2",
|
|
59
|
-
"sass-loader": "13.3.1",
|
|
60
|
-
"semver": "^7.6.3",
|
|
55
|
+
"sass-loader": "13.3.1",
|
|
56
|
+
"semver": "^7.6.3",
|
|
61
57
|
"style-loader": "3.3.3",{{#unless useExperimentalRspack}}
|
|
62
58
|
"swc-loader": "^0.2.3",{{/unless}}
|
|
63
59
|
"terser-webpack-plugin": "^5.3.10",
|
package/templates/common/npmrc
CHANGED
|
@@ -10,6 +10,3 @@ public-hoist-pattern[]="*prettier*"
|
|
|
10
10
|
# Hoist all types packages to the root for better TS support
|
|
11
11
|
public-hoist-pattern[]="@types/*"
|
|
12
12
|
public-hoist-pattern[]="*terser-webpack-plugin*"
|
|
13
|
-
{{#unless usePlaywright}}
|
|
14
|
-
# @grafana/e2e expects cypress to exist in the root of the node_modules directory
|
|
15
|
-
public-hoist-pattern[]="*cypress*"{{/unless}}
|
|
@@ -146,7 +146,7 @@ jobs:
|
|
|
146
146
|
|
|
147
147
|
- name: Resolve Grafana E2E versions
|
|
148
148
|
id: resolve-versions
|
|
149
|
-
uses: grafana/plugin-actions/e2e-version@
|
|
149
|
+
uses: grafana/plugin-actions/e2e-version@v1.1.2
|
|
150
150
|
|
|
151
151
|
playwright-tests:
|
|
152
152
|
needs: [resolve-versions, build]
|
|
@@ -197,7 +197,7 @@ jobs:
|
|
|
197
197
|
ANONYMOUS_AUTH_ENABLED=false DEVELOPMENT=false GRAFANA_VERSION=$\{{ matrix.GRAFANA_IMAGE.VERSION }} GRAFANA_IMAGE=$\{{ matrix.GRAFANA_IMAGE.NAME }} docker compose up -d
|
|
198
198
|
|
|
199
199
|
- name: Wait for grafana server
|
|
200
|
-
uses: grafana/plugin-actions/wait-for-grafana@
|
|
200
|
+
uses: grafana/plugin-actions/wait-for-grafana@v1.0.2
|
|
201
201
|
with:
|
|
202
202
|
url: http://localhost:3000/login
|
|
203
203
|
|
|
@@ -209,7 +209,7 @@ jobs:
|
|
|
209
209
|
run: {{ packageManagerName }} run e2e
|
|
210
210
|
|
|
211
211
|
- name: Upload e2e test summary
|
|
212
|
-
uses: grafana/plugin-actions/playwright-gh-pages/upload-report-artifacts@
|
|
212
|
+
uses: grafana/plugin-actions/playwright-gh-pages/upload-report-artifacts@v1.0.1
|
|
213
213
|
if: $\{{ always() && !cancelled() }}
|
|
214
214
|
with:
|
|
215
215
|
upload-report: false
|
|
@@ -247,7 +247,7 @@ jobs:
|
|
|
247
247
|
# required for playwright-gh-pages
|
|
248
248
|
persist-credentials: true
|
|
249
249
|
- name: Publish report
|
|
250
|
-
uses: grafana/plugin-actions/playwright-gh-pages/deploy-report-pages@
|
|
250
|
+
uses: grafana/plugin-actions/playwright-gh-pages/deploy-report-pages@v1.0.1
|
|
251
251
|
with:
|
|
252
252
|
github-token: $\{{ secrets.GITHUB_TOKEN }}
|
|
253
253
|
|
|
@@ -18,7 +18,7 @@ jobs:
|
|
|
18
18
|
release:
|
|
19
19
|
runs-on: ubuntu-latest
|
|
20
20
|
steps:
|
|
21
|
-
- uses: grafana/plugin-actions/create-plugin-update@
|
|
21
|
+
- uses: grafana/plugin-actions/create-plugin-update@v1.1.0
|
|
22
22
|
# Uncomment to use a fine-grained personal access token instead of default github token
|
|
23
23
|
# (For more info on how to generate the token see https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
|
|
24
24
|
# with:
|
|
@@ -36,7 +36,7 @@ jobs:
|
|
|
36
36
|
echo "modulets=${MODULETS}" >> $GITHUB_OUTPUT
|
|
37
37
|
|
|
38
38
|
- name: Compatibility check
|
|
39
|
-
uses: grafana/plugin-actions/is-compatible@
|
|
39
|
+
uses: grafana/plugin-actions/is-compatible@v1.0.2
|
|
40
40
|
with:
|
|
41
41
|
module: $\{{ steps.find-module-ts.outputs.modulets }}
|
|
42
42
|
comment-pr: "no"
|
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
with:
|
|
21
21
|
persist-credentials: false
|
|
22
22
|
|
|
23
|
-
- uses: grafana/plugin-actions/build-plugin@
|
|
23
|
+
- uses: grafana/plugin-actions/build-plugin@v1.0.2
|
|
24
24
|
# Uncomment to enable plugin signing
|
|
25
25
|
# (For more info on how to generate the access policy token see https://grafana.com/developers/plugin-tools/publish-a-plugin/sign-a-plugin#generate-an-access-policy-token)
|
|
26
26
|
#with:
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import Enquirer from 'enquirer';
|
|
2
|
-
import { output } from '../../utils/utils.console.js';
|
|
3
|
-
|
|
4
|
-
const COMMON_LOCALES = [
|
|
5
|
-
{ name: "en-US", message: "English (US)" },
|
|
6
|
-
{ name: "es-ES", message: "Spanish (Spain)" },
|
|
7
|
-
{ name: "fr-FR", message: "French (France)" },
|
|
8
|
-
{ name: "de-DE", message: "German (Germany)" },
|
|
9
|
-
{ name: "zh-Hans", message: "Chinese (Simplified)" },
|
|
10
|
-
{ name: "pt-BR", message: "Portuguese (Brazil)" },
|
|
11
|
-
{ name: "sv-SE", message: "Swedish (Sweden)" },
|
|
12
|
-
{ name: "nl-NL", message: "Dutch (Netherlands)" },
|
|
13
|
-
{ name: "ja-JP", message: "Japanese (Japan)" },
|
|
14
|
-
{ name: "it-IT", message: "Italian (Italy)" }
|
|
15
|
-
];
|
|
16
|
-
async function promptI18nOptions() {
|
|
17
|
-
const enquirer = new Enquirer();
|
|
18
|
-
output.log({
|
|
19
|
-
title: "Configure internationalization (i18n) for your plugin",
|
|
20
|
-
body: [
|
|
21
|
-
"Select the locales you want to support. At least one locale must be selected.",
|
|
22
|
-
"Use space to select, enter to continue."
|
|
23
|
-
]
|
|
24
|
-
});
|
|
25
|
-
const localeChoices = COMMON_LOCALES.map((locale) => ({
|
|
26
|
-
name: locale.name,
|
|
27
|
-
message: locale.message,
|
|
28
|
-
value: locale.name
|
|
29
|
-
}));
|
|
30
|
-
let selectedLocales = [];
|
|
31
|
-
try {
|
|
32
|
-
const result = await enquirer.prompt({
|
|
33
|
-
type: "multiselect",
|
|
34
|
-
name: "locales",
|
|
35
|
-
message: "Select locales to support:",
|
|
36
|
-
choices: localeChoices,
|
|
37
|
-
initial: [0],
|
|
38
|
-
// Pre-select en-US by default
|
|
39
|
-
validate(value) {
|
|
40
|
-
if (value.length === 0) {
|
|
41
|
-
return "At least one locale must be selected";
|
|
42
|
-
}
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
selectedLocales = result.locales;
|
|
47
|
-
} catch (error) {
|
|
48
|
-
output.warning({ title: "Addition cancelled by user." });
|
|
49
|
-
process.exit(0);
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
const addMoreResult = await enquirer.prompt({
|
|
53
|
-
type: "input",
|
|
54
|
-
name: "additionalLocales",
|
|
55
|
-
message: 'Enter additional locale codes (comma-separated, e.g., "ko-KR,ru-RU") or press enter to skip:'
|
|
56
|
-
});
|
|
57
|
-
const additionalLocalesInput = addMoreResult.additionalLocales;
|
|
58
|
-
if (additionalLocalesInput && additionalLocalesInput.trim()) {
|
|
59
|
-
const additionalLocales = additionalLocalesInput.split(",").map((locale) => locale.trim()).filter((locale) => locale.length > 0 && !selectedLocales.includes(locale));
|
|
60
|
-
selectedLocales.push(...additionalLocales);
|
|
61
|
-
}
|
|
62
|
-
} catch (error) {
|
|
63
|
-
}
|
|
64
|
-
output.log({
|
|
65
|
-
title: `Selected locales: ${selectedLocales.join(", ")}`
|
|
66
|
-
});
|
|
67
|
-
return {
|
|
68
|
-
locales: selectedLocales
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export { promptI18nOptions };
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import Enquirer from 'enquirer';
|
|
2
|
-
import { output } from '../../utils/utils.console.js';
|
|
3
|
-
|
|
4
|
-
// Common locales supported by Grafana
|
|
5
|
-
// Reference: https://github.com/grafana/grafana/blob/main/packages/grafana-i18n/src/constants.ts
|
|
6
|
-
const COMMON_LOCALES = [
|
|
7
|
-
{ name: 'en-US', message: 'English (US)' },
|
|
8
|
-
{ name: 'es-ES', message: 'Spanish (Spain)' },
|
|
9
|
-
{ name: 'fr-FR', message: 'French (France)' },
|
|
10
|
-
{ name: 'de-DE', message: 'German (Germany)' },
|
|
11
|
-
{ name: 'zh-Hans', message: 'Chinese (Simplified)' },
|
|
12
|
-
{ name: 'pt-BR', message: 'Portuguese (Brazil)' },
|
|
13
|
-
{ name: 'sv-SE', message: 'Swedish (Sweden)' },
|
|
14
|
-
{ name: 'nl-NL', message: 'Dutch (Netherlands)' },
|
|
15
|
-
{ name: 'ja-JP', message: 'Japanese (Japan)' },
|
|
16
|
-
{ name: 'it-IT', message: 'Italian (Italy)' },
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
export type I18nOptions = {
|
|
20
|
-
locales: string[];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export async function promptI18nOptions(): Promise<I18nOptions> {
|
|
24
|
-
const enquirer = new Enquirer();
|
|
25
|
-
|
|
26
|
-
output.log({
|
|
27
|
-
title: 'Configure internationalization (i18n) for your plugin',
|
|
28
|
-
body: [
|
|
29
|
-
'Select the locales you want to support. At least one locale must be selected.',
|
|
30
|
-
'Use space to select, enter to continue.',
|
|
31
|
-
],
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const localeChoices = COMMON_LOCALES.map((locale) => ({
|
|
35
|
-
name: locale.name,
|
|
36
|
-
message: locale.message,
|
|
37
|
-
value: locale.name,
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
|
-
let selectedLocales: string[] = [];
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const result = (await enquirer.prompt({
|
|
44
|
-
type: 'multiselect',
|
|
45
|
-
name: 'locales',
|
|
46
|
-
message: 'Select locales to support:',
|
|
47
|
-
choices: localeChoices,
|
|
48
|
-
initial: [0], // Pre-select en-US by default
|
|
49
|
-
validate(value: string[]) {
|
|
50
|
-
if (value.length === 0) {
|
|
51
|
-
return 'At least one locale must be selected';
|
|
52
|
-
}
|
|
53
|
-
return true;
|
|
54
|
-
},
|
|
55
|
-
} as any)) as { locales: string[] };
|
|
56
|
-
|
|
57
|
-
selectedLocales = result.locales;
|
|
58
|
-
} catch (error) {
|
|
59
|
-
// User cancelled the prompt
|
|
60
|
-
output.warning({ title: 'Addition cancelled by user.' });
|
|
61
|
-
process.exit(0);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Ask if they want to add additional locales
|
|
65
|
-
try {
|
|
66
|
-
const addMoreResult = (await enquirer.prompt({
|
|
67
|
-
type: 'input',
|
|
68
|
-
name: 'additionalLocales',
|
|
69
|
-
message: 'Enter additional locale codes (comma-separated, e.g., "ko-KR,ru-RU") or press enter to skip:',
|
|
70
|
-
} as any)) as { additionalLocales: string };
|
|
71
|
-
|
|
72
|
-
const additionalLocalesInput = addMoreResult.additionalLocales;
|
|
73
|
-
|
|
74
|
-
if (additionalLocalesInput && additionalLocalesInput.trim()) {
|
|
75
|
-
const additionalLocales = additionalLocalesInput
|
|
76
|
-
.split(',')
|
|
77
|
-
.map((locale: string) => locale.trim())
|
|
78
|
-
.filter((locale: string) => locale.length > 0 && !selectedLocales.includes(locale));
|
|
79
|
-
|
|
80
|
-
selectedLocales.push(...additionalLocales);
|
|
81
|
-
}
|
|
82
|
-
} catch (error) {
|
|
83
|
-
// User cancelled, just continue with what we have
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
output.log({
|
|
87
|
-
title: `Selected locales: ${selectedLocales.join(', ')}`,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
locales: selectedLocales,
|
|
92
|
-
};
|
|
93
|
-
}
|