Skip to content

Commit 0121ba1

Browse files
committed
refactor(create-plugin): make additions self-contained with dynamic flag loading
- Each addition script now exports its own flags and parseFlags function - Removed prompts.ts in favor of CLI flags - Manager dynamically loads flags from addition scripts - Simplified additions.ts to only contain metadata - Makes adding new additions fully plug-and-play without touching core files
1 parent 05e1a7c commit 0121ba1

File tree

5 files changed

+102
-113
lines changed

5 files changed

+102
-113
lines changed

packages/create-plugin/src/additions/additions.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ export type AdditionMeta = {
44
scriptPath: string;
55
};
66

7-
type Additions = {
8-
additions: Record<string, AdditionMeta>;
9-
};
10-
117
export default {
128
additions: {
139
i18n: {
@@ -16,4 +12,4 @@ export default {
1612
scriptPath: './scripts/add-i18n.js',
1713
},
1814
},
19-
} as Additions;
15+
};

packages/create-plugin/src/additions/manager.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@ export function getAdditionByName(
2626
return additions[name];
2727
}
2828

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+
2950
export async function runAddition(
3051
addition: AdditionMeta,
3152
additionOptions: AdditionOptions = {},

packages/create-plugin/src/additions/scripts/add-i18n.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ export type I18nOptions = {
1212
locales: string[];
1313
};
1414

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+
1531
export default function migrate(context: Context, options: I18nOptions = { locales: ['en-US'] }): Context {
1632
const { locales } = options;
1733

packages/create-plugin/src/commands/add.command.ts

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,41 @@
1-
import { getAdditionByName, getAvailableAdditions, runAddition } from '../additions/manager.js';
1+
import {
2+
AdditionOptions,
3+
getAdditionByName,
4+
getAdditionFlags,
5+
getAvailableAdditions,
6+
parseAdditionFlags,
7+
runAddition,
8+
} from '../additions/manager.js';
29
import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
310

411
import { isPluginDirectory } from '../utils/utils.plugin.js';
512
import minimist from 'minimist';
613
import { output } from '../utils/utils.console.js';
7-
import { promptI18nOptions } from './add/prompts.js';
814

915
export const add = async (argv: minimist.ParsedArgs) => {
1016
const subCommand = argv._[1];
1117

1218
if (!subCommand) {
1319
const availableAdditions = getAvailableAdditions();
14-
const additionsList = Object.values(availableAdditions).map(
15-
(addition) => `${addition.name} - ${addition.description}`
20+
const additionsList = await Promise.all(
21+
Object.values(availableAdditions).map(async (addition) => {
22+
let info = `${addition.name} - ${addition.description}`;
23+
const flags = await getAdditionFlags(addition);
24+
if (flags.length > 0) {
25+
const flagDocs = flags.map((flag) => {
26+
const req = flag.required ? ' (required)' : ' (optional)';
27+
return ` --${flag.name}: ${flag.description}${req}`;
28+
});
29+
info += '\n' + flagDocs.join('\n');
30+
}
31+
return info;
32+
})
1633
);
1734

1835
output.error({
1936
title: 'No addition specified',
2037
body: [
21-
'Usage: npx @grafana/create-plugin add <addition-name>',
38+
'Usage: npx @grafana/create-plugin add <addition-name> [options]',
2239
'',
2340
'Available additions:',
2441
...output.bulletList(additionsList),
@@ -43,16 +60,11 @@ export const add = async (argv: minimist.ParsedArgs) => {
4360
}
4461

4562
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-
}
63+
// Parse addition-specific options from argv flags using the addition's own parser
64+
const options = await parseAdditionFlags(addition, argv);
65+
66+
// Validate required flags
67+
await validateAdditionOptions(addition, options);
5668

5769
const commitChanges = argv.commit;
5870
await runAddition(addition, options, { commitChanges });
@@ -67,6 +79,43 @@ export const add = async (argv: minimist.ParsedArgs) => {
6779
}
6880
};
6981

82+
async function validateAdditionOptions(addition: any, options: AdditionOptions): Promise<void> {
83+
const flags = await getAdditionFlags(addition);
84+
85+
if (!flags || flags.length === 0) {
86+
return;
87+
}
88+
89+
const missingFlags: string[] = [];
90+
91+
for (const flag of flags) {
92+
if (flag.required) {
93+
const value = options[flag.name];
94+
if (value === undefined || value === null || (Array.isArray(value) && value.length === 0)) {
95+
missingFlags.push(flag.name);
96+
}
97+
}
98+
}
99+
100+
if (missingFlags.length > 0) {
101+
const flagDocs = flags
102+
.filter((f: any) => missingFlags.includes(f.name))
103+
.map((f: any) => ` --${f.name}: ${f.description}`);
104+
105+
output.error({
106+
title: `Missing required flag${missingFlags.length > 1 ? 's' : ''}`,
107+
body: [
108+
`The following required flag${missingFlags.length > 1 ? 's are' : ' is'} missing:`,
109+
'',
110+
...flagDocs,
111+
'',
112+
`Example: npx @grafana/create-plugin add ${addition.name} --${missingFlags[0]}=value`,
113+
],
114+
});
115+
process.exit(1);
116+
}
117+
}
118+
70119
async function performPreAddChecks(argv: minimist.ParsedArgs) {
71120
if (!(await isGitDirectory()) && !argv.force) {
72121
output.error({

packages/create-plugin/src/commands/add/prompts.ts

Lines changed: 0 additions & 93 deletions
This file was deleted.

0 commit comments

Comments
 (0)