@grafana/create-plugin 6.1.1 → 6.2.0-canary.2233.18644853669.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 +0 -12
- package/README.md +39 -0
- package/dist/additions/additions.js +11 -0
- package/dist/additions/manager.js +48 -0
- package/dist/additions/scripts/add-i18n.js +433 -0
- package/dist/additions/utils.js +28 -0
- package/dist/bin/run.js +4 -2
- package/dist/commands/add/prompts.js +72 -0
- package/dist/commands/add.command.js +92 -0
- package/package.json +2 -2
- package/src/additions/additions.ts +19 -0
- package/src/additions/manager.ts +77 -0
- package/src/additions/scripts/add-i18n.test.ts +347 -0
- package/src/additions/scripts/add-i18n.ts +568 -0
- package/src/additions/utils.ts +39 -0
- package/src/bin/run.ts +5 -3
- package/src/commands/add/prompts.ts +93 -0
- package/src/commands/add.command.ts +108 -0
- package/src/commands/index.ts +1 -0
- package/templates/common/_package.json +1 -1
|
@@ -0,0 +1,93 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { getAdditionByName, getAvailableAdditions, runAddition } from '../additions/manager.js';
|
|
2
|
+
import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
|
|
3
|
+
|
|
4
|
+
import { isPluginDirectory } from '../utils/utils.plugin.js';
|
|
5
|
+
import minimist from 'minimist';
|
|
6
|
+
import { output } from '../utils/utils.console.js';
|
|
7
|
+
import { promptI18nOptions } from './add/prompts.js';
|
|
8
|
+
|
|
9
|
+
export const add = async (argv: minimist.ParsedArgs) => {
|
|
10
|
+
const subCommand = argv._[1];
|
|
11
|
+
|
|
12
|
+
if (!subCommand) {
|
|
13
|
+
const availableAdditions = getAvailableAdditions();
|
|
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
|
+
});
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await performPreAddChecks(argv);
|
|
31
|
+
|
|
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
|
+
try {
|
|
46
|
+
// Gather options based on the addition type
|
|
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 });
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error instanceof Error) {
|
|
61
|
+
output.error({
|
|
62
|
+
title: 'Addition failed',
|
|
63
|
+
body: [error.message],
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
async function performPreAddChecks(argv: minimist.ParsedArgs) {
|
|
71
|
+
if (!(await isGitDirectory()) && !argv.force) {
|
|
72
|
+
output.error({
|
|
73
|
+
title: 'You are not inside a git directory',
|
|
74
|
+
body: [
|
|
75
|
+
`In order to proceed please run ${output.formatCode('git init')} in the root of your project and commit your changes.`,
|
|
76
|
+
`(This check is necessary to make sure that the changes are easy to revert and don't interfere with any changes you currently have.`,
|
|
77
|
+
`In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!(await isGitDirectoryClean()) && !argv.force) {
|
|
85
|
+
output.error({
|
|
86
|
+
title: 'Please clean your repository working tree before adding features.',
|
|
87
|
+
body: [
|
|
88
|
+
'Commit your changes or stash them.',
|
|
89
|
+
`(This check is necessary to make sure that the changes are easy to revert and don't mess with any changes you currently have.`,
|
|
90
|
+
`In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
|
|
91
|
+
],
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!isPluginDirectory() && !argv.force) {
|
|
98
|
+
output.error({
|
|
99
|
+
title: 'Are you inside a plugin directory?',
|
|
100
|
+
body: [
|
|
101
|
+
`We couldn't find a "src/plugin.json" file under your current directory.`,
|
|
102
|
+
`(Please make sure to run this command from the root of your plugin folder. In case you want to proceed as is please use the ${output.formatCode('--force')} flag.)`,
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
package/src/commands/index.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"license": "Apache-2.0",
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
{{#if useCypress}} "@grafana/e2e": "^11.0.7",
|
|
22
|
-
"@grafana/e2e-selectors": "^12.
|
|
22
|
+
"@grafana/e2e-selectors": "^12.2.0",{{/if}}
|
|
23
23
|
"@grafana/eslint-config": "^8.2.0",{{#if usePlaywright}}
|
|
24
24
|
"@grafana/plugin-e2e": "^2.2.0",{{/if}}
|
|
25
25
|
"@grafana/tsconfig": "^2.0.0",{{#if usePlaywright}}
|