@grafana/create-plugin 2.11.0-canary.634.15520dc.0 → 2.11.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/commands/{generate-actions → generate}/prettify-files.js +8 -11
- package/dist/commands/{generate-actions → generate}/print-success-message.js +2 -2
- package/dist/commands/generate/prompt-user.js +145 -0
- package/dist/commands/{generate-actions → generate}/update-go-sdk-and-packages.js +10 -13
- package/dist/commands/generate.command.js +225 -9
- package/dist/utils/utils.console.js +5 -2
- package/dist/utils/utils.files.js +58 -1
- package/dist/utils/utils.handlebars.js +14 -3
- package/package.json +22 -15
- package/src/commands/{generate-actions → generate}/prettify-files.ts +1 -5
- package/src/commands/{generate-actions → generate}/print-success-message.ts +2 -3
- package/src/commands/generate/prompt-user.ts +102 -0
- package/src/commands/{generate-actions → generate}/update-go-sdk-and-packages.ts +1 -6
- package/src/commands/generate.command.ts +194 -11
- package/src/utils/utils.console.ts +5 -2
- package/src/utils/utils.files.ts +10 -0
- package/src/utils/utils.handlebars.ts +17 -4
- package/templates/app/README.md +3 -3
- package/templates/datasource/README.md +3 -3
- package/templates/panel/README.md +2 -2
- package/templates/scenes-app/README.md +2 -2
- package/dist/commands/generate.plopfile.js +0 -214
- package/scripts/generate-app-backend.js +0 -29
- package/scripts/generate-app.js +0 -29
- package/scripts/generate-datasource-with-backend.js +0 -29
- package/scripts/generate-datasource-without-backend.js +0 -29
- package/scripts/generate-panel.js +0 -28
- package/scripts/generate-scenes-app.js +0 -29
- package/src/commands/generate.plopfile.ts +0 -272
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
14
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
15
|
-
if (ar || !(i in from)) {
|
|
16
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
17
|
-
ar[i] = from[i];
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
21
|
-
};
|
|
22
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
23
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
var fs_1 = __importDefault(require("fs"));
|
|
27
|
-
var glob_1 = __importDefault(require("glob"));
|
|
28
|
-
var path_1 = __importDefault(require("path"));
|
|
29
|
-
var constants_1 = require("../constants");
|
|
30
|
-
var utils_handlebars_1 = require("../utils/utils.handlebars");
|
|
31
|
-
var utils_path_1 = require("../utils/utils.path");
|
|
32
|
-
var utils_packageManager_1 = require("../utils/utils.packageManager");
|
|
33
|
-
var print_success_message_1 = require("./generate-actions/print-success-message");
|
|
34
|
-
var update_go_sdk_and_packages_1 = require("./generate-actions/update-go-sdk-and-packages");
|
|
35
|
-
var prettify_files_1 = require("./generate-actions/prettify-files");
|
|
36
|
-
var utils_files_1 = require("../utils/utils.files");
|
|
37
|
-
var utils_config_1 = require("../utils/utils.config");
|
|
38
|
-
var utils_version_1 = require("../utils/utils.version");
|
|
39
|
-
function default_1(plop) {
|
|
40
|
-
plop.setHelper('if_eq', utils_handlebars_1.ifEq);
|
|
41
|
-
plop.setHelper('normalize_id', utils_handlebars_1.normalizeId);
|
|
42
|
-
plop.setActionType('printSuccessMessage', print_success_message_1.printGenerateSuccessMessage);
|
|
43
|
-
plop.setActionType('prettifyFiles', prettify_files_1.prettifyFiles);
|
|
44
|
-
plop.setActionType('updateGoSdkAndModules', update_go_sdk_and_packages_1.updateGoSdkAndModules);
|
|
45
|
-
plop.setGenerator('create-plugin', {
|
|
46
|
-
description: 'used to scaffold a grafana plugin',
|
|
47
|
-
prompts: [
|
|
48
|
-
{
|
|
49
|
-
name: 'pluginName',
|
|
50
|
-
type: 'input',
|
|
51
|
-
message: 'What is going to be the name of your plugin?',
|
|
52
|
-
validate: function (value) {
|
|
53
|
-
if (/.+/.test(value)) {
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
return 'Plugin name is required';
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
name: 'orgName',
|
|
61
|
-
type: 'input',
|
|
62
|
-
message: 'What is the organization name of your plugin?',
|
|
63
|
-
validate: function (value) {
|
|
64
|
-
if (/.+/.test(value)) {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
return 'Organization name is required';
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'pluginDescription',
|
|
72
|
-
type: 'input',
|
|
73
|
-
message: 'How would you describe your plugin?',
|
|
74
|
-
default: '',
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: 'pluginType',
|
|
78
|
-
type: 'list',
|
|
79
|
-
choices: [constants_1.PLUGIN_TYPES.app, constants_1.PLUGIN_TYPES.datasource, constants_1.PLUGIN_TYPES.panel, constants_1.PLUGIN_TYPES.scenes],
|
|
80
|
-
message: 'What type of plugin would you like?',
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
name: 'hasBackend',
|
|
84
|
-
type: 'confirm',
|
|
85
|
-
message: 'Do you want a backend part of your plugin?',
|
|
86
|
-
default: false,
|
|
87
|
-
when: function (answers) { return answers.pluginType !== constants_1.PLUGIN_TYPES.panel; },
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
name: 'hasGithubWorkflows',
|
|
91
|
-
type: 'confirm',
|
|
92
|
-
message: 'Do you want to add Github CI and Release workflows?',
|
|
93
|
-
default: false,
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: 'hasGithubLevitateWorkflow',
|
|
97
|
-
type: 'confirm',
|
|
98
|
-
message: 'Do you want to add a Github workflow for automatically checking "Grafana API compatibility" on PRs?',
|
|
99
|
-
default: false,
|
|
100
|
-
},
|
|
101
|
-
],
|
|
102
|
-
actions: function (_a) {
|
|
103
|
-
var pluginName = _a.pluginName, orgName = _a.orgName, pluginType = _a.pluginType, hasBackend = _a.hasBackend, hasGithubWorkflows = _a.hasGithubWorkflows, hasGithubLevitateWorkflow = _a.hasGithubLevitateWorkflow;
|
|
104
|
-
var features = (0, utils_config_1.getConfig)().features;
|
|
105
|
-
var currentVersion = (0, utils_version_1.getVersion)();
|
|
106
|
-
var exportPath = (0, utils_path_1.getExportPath)(pluginName, orgName, pluginType);
|
|
107
|
-
var pluginId = (0, utils_handlebars_1.normalizeId)(pluginName, orgName, pluginType);
|
|
108
|
-
var _b = (0, utils_packageManager_1.getPackageManagerFromUserAgent)(), packageManagerName = _b.packageManagerName, packageManagerVersion = _b.packageManagerVersion;
|
|
109
|
-
var packageManagerInstallCmd = (0, utils_packageManager_1.getPackageManagerInstallCmd)(packageManagerName);
|
|
110
|
-
var isAppType = pluginType === constants_1.PLUGIN_TYPES.app || pluginType === constants_1.PLUGIN_TYPES.scenes;
|
|
111
|
-
var templateData = {
|
|
112
|
-
pluginId: pluginId,
|
|
113
|
-
packageManagerName: packageManagerName,
|
|
114
|
-
packageManagerInstallCmd: packageManagerInstallCmd,
|
|
115
|
-
packageManagerVersion: packageManagerVersion,
|
|
116
|
-
isAppType: isAppType,
|
|
117
|
-
isNPM: packageManagerName === 'npm',
|
|
118
|
-
version: currentVersion,
|
|
119
|
-
bundleGrafanaUI: features.bundleGrafanaUI,
|
|
120
|
-
};
|
|
121
|
-
var commonActions = getActionsForTemplateFolder({
|
|
122
|
-
folderPath: constants_1.TEMPLATE_PATHS.common,
|
|
123
|
-
exportPath: exportPath,
|
|
124
|
-
templateData: templateData,
|
|
125
|
-
});
|
|
126
|
-
var pluginTypeSpecificActions = getActionsForTemplateFolder({
|
|
127
|
-
folderPath: constants_1.TEMPLATE_PATHS[pluginType],
|
|
128
|
-
exportPath: exportPath,
|
|
129
|
-
templateData: templateData,
|
|
130
|
-
});
|
|
131
|
-
var backendFolderPath = isAppType ? constants_1.TEMPLATE_PATHS.backendApp : constants_1.TEMPLATE_PATHS.backend;
|
|
132
|
-
var backendActions = hasBackend
|
|
133
|
-
? getActionsForTemplateFolder({ folderPath: backendFolderPath, exportPath: exportPath, templateData: templateData })
|
|
134
|
-
: [];
|
|
135
|
-
var pluginActions = __spreadArray(__spreadArray(__spreadArray([], backendActions, true), pluginTypeSpecificActions, true), commonActions, true).reduce(function (acc, file) {
|
|
136
|
-
var actionExists = acc.find(function (f) { return f.path === file.path; });
|
|
137
|
-
if (actionExists && actionExists.type === 'add' && file.type === 'add') {
|
|
138
|
-
return acc;
|
|
139
|
-
}
|
|
140
|
-
acc.push(file);
|
|
141
|
-
return acc;
|
|
142
|
-
}, []);
|
|
143
|
-
var ciWorkflowActions = hasGithubWorkflows
|
|
144
|
-
? getActionsForTemplateFolder({
|
|
145
|
-
folderPath: constants_1.TEMPLATE_PATHS.ciWorkflows,
|
|
146
|
-
exportPath: exportPath,
|
|
147
|
-
templateData: templateData,
|
|
148
|
-
})
|
|
149
|
-
: [];
|
|
150
|
-
var isCompatibleWorkflowActions = hasGithubLevitateWorkflow
|
|
151
|
-
? getActionsForTemplateFolder({
|
|
152
|
-
folderPath: constants_1.TEMPLATE_PATHS.isCompatibleWorkflow,
|
|
153
|
-
exportPath: exportPath,
|
|
154
|
-
templateData: templateData,
|
|
155
|
-
})
|
|
156
|
-
: [];
|
|
157
|
-
var readmeActions = getActionsForReadme({ exportPath: exportPath, templateData: templateData });
|
|
158
|
-
return __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], pluginActions, true), ciWorkflowActions, true), readmeActions, true), isCompatibleWorkflowActions, true), [
|
|
159
|
-
{
|
|
160
|
-
type: 'updateGoSdkAndModules',
|
|
161
|
-
},
|
|
162
|
-
{ type: 'prettifyFiles' },
|
|
163
|
-
{
|
|
164
|
-
type: 'printSuccessMessage',
|
|
165
|
-
},
|
|
166
|
-
], false);
|
|
167
|
-
},
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
exports.default = default_1;
|
|
171
|
-
function getActionsForReadme(_a) {
|
|
172
|
-
var exportPath = _a.exportPath, templateData = _a.templateData;
|
|
173
|
-
return [
|
|
174
|
-
replacePatternWithTemplateInReadme('-- INSERT FRONTEND GETTING STARTED --', 'frontend-getting-started.md', exportPath, templateData),
|
|
175
|
-
replacePatternWithTemplateInReadme('-- INSERT BACKEND GETTING STARTED --', 'backend-getting-started.md', exportPath, templateData),
|
|
176
|
-
replacePatternWithTemplateInReadme('-- INSERT DISTRIBUTING YOUR PLUGIN --', 'distributing-your-plugin.md', exportPath, templateData),
|
|
177
|
-
];
|
|
178
|
-
}
|
|
179
|
-
function replacePatternWithTemplateInReadme(pattern, partialsFile, exportPath, templateData) {
|
|
180
|
-
return {
|
|
181
|
-
type: 'modify',
|
|
182
|
-
path: path_1.default.join(exportPath, 'README.md'),
|
|
183
|
-
pattern: pattern,
|
|
184
|
-
template: undefined,
|
|
185
|
-
templateFile: path_1.default.join(constants_1.PARTIALS_DIR, partialsFile),
|
|
186
|
-
data: __assign(__assign({}, constants_1.EXTRA_TEMPLATE_VARIABLES), templateData),
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
function getActionsForTemplateFolder(_a) {
|
|
190
|
-
var folderPath = _a.folderPath, exportPath = _a.exportPath, templateData = _a.templateData;
|
|
191
|
-
var files = glob_1.default.sync("".concat(folderPath, "/**"), { dot: true });
|
|
192
|
-
if (templateData.packageManagerName !== 'pnpm') {
|
|
193
|
-
files = files.filter(function (file) { return path_1.default.basename(file) !== 'npmrc'; });
|
|
194
|
-
}
|
|
195
|
-
function getExportPath(f) {
|
|
196
|
-
return path_1.default.relative(folderPath, path_1.default.dirname(f));
|
|
197
|
-
}
|
|
198
|
-
return files.filter(isFile).map(function (f) { return ({
|
|
199
|
-
type: 'add',
|
|
200
|
-
templateFile: f,
|
|
201
|
-
path: path_1.default.join(exportPath, getExportPath(f), (0, utils_files_1.getExportFileName)(f)),
|
|
202
|
-
force: constants_1.IS_DEV,
|
|
203
|
-
abortOnFail: false,
|
|
204
|
-
data: __assign(__assign({}, constants_1.EXTRA_TEMPLATE_VARIABLES), templateData),
|
|
205
|
-
}); });
|
|
206
|
-
}
|
|
207
|
-
function isFile(path) {
|
|
208
|
-
try {
|
|
209
|
-
return fs_1.default.lstatSync(path).isFile();
|
|
210
|
-
}
|
|
211
|
-
catch (e) {
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const nodePlop = require('node-plop');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
async function generate() {
|
|
6
|
-
const plopFile = path.join(__dirname, '../dist/commands/generate.plopfile.js');
|
|
7
|
-
if (!fs.existsSync(plopFile)) {
|
|
8
|
-
console.error('Run build first');
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
const plop = await nodePlop(plopFile);
|
|
12
|
-
const generator = plop.getGenerator('create-plugin');
|
|
13
|
-
await generator.runActions(
|
|
14
|
-
{
|
|
15
|
-
pluginName: 'my-plugin',
|
|
16
|
-
orgName: 'my-org',
|
|
17
|
-
pluginDescription: 'Auto-generated app with backend',
|
|
18
|
-
pluginType: 'app',
|
|
19
|
-
hasBackend: true,
|
|
20
|
-
hasGithubWorkflows: true,
|
|
21
|
-
hasGithubLevitateWorkflow: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
onFailure: console.error,
|
|
25
|
-
}
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
generate();
|
package/scripts/generate-app.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const nodePlop = require('node-plop');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
async function generate() {
|
|
6
|
-
const plopFile = path.join(__dirname, '../dist/commands/generate.plopfile.js');
|
|
7
|
-
if (!fs.existsSync(plopFile)) {
|
|
8
|
-
console.error('Run build first');
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
const plop = await nodePlop(plopFile);
|
|
12
|
-
const generator = plop.getGenerator('create-plugin');
|
|
13
|
-
await generator.runActions(
|
|
14
|
-
{
|
|
15
|
-
pluginName: 'my-plugin',
|
|
16
|
-
orgName: 'my-org',
|
|
17
|
-
pluginDescription: 'Auto-generated app',
|
|
18
|
-
pluginType: 'app',
|
|
19
|
-
hasBackend: false,
|
|
20
|
-
hasGithubWorkflows: true,
|
|
21
|
-
hasGithubLevitateWorkflow: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
onFailure: console.error,
|
|
25
|
-
}
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
generate();
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const nodePlop = require('node-plop');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
async function generate() {
|
|
6
|
-
const plopFile = path.join(__dirname, '../dist/commands/generate.plopfile.js');
|
|
7
|
-
if (!fs.existsSync(plopFile)) {
|
|
8
|
-
console.error('Run build first');
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
const plop = await nodePlop(plopFile);
|
|
12
|
-
const generator = plop.getGenerator('create-plugin');
|
|
13
|
-
await generator.runActions(
|
|
14
|
-
{
|
|
15
|
-
pluginName: 'my-plugin',
|
|
16
|
-
orgName: 'my-org',
|
|
17
|
-
pluginDescription: 'Auto-generated datasource',
|
|
18
|
-
pluginType: 'datasource',
|
|
19
|
-
hasBackend: true,
|
|
20
|
-
hasGithubWorkflows: true,
|
|
21
|
-
hasGithubLevitateWorkflow: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
onFailure: console.error,
|
|
25
|
-
}
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
generate();
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const nodePlop = require('node-plop');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
async function generate() {
|
|
6
|
-
const plopFile = path.join(__dirname, '../dist/commands/generate.plopfile.js');
|
|
7
|
-
if (!fs.existsSync(plopFile)) {
|
|
8
|
-
console.error('Run build first');
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
const plop = await nodePlop(plopFile);
|
|
12
|
-
const generator = plop.getGenerator('create-plugin');
|
|
13
|
-
await generator.runActions(
|
|
14
|
-
{
|
|
15
|
-
pluginName: 'my-plugin',
|
|
16
|
-
orgName: 'my-org',
|
|
17
|
-
pluginDescription: 'Auto-generated datasource',
|
|
18
|
-
pluginType: 'datasource',
|
|
19
|
-
hasBackend: false,
|
|
20
|
-
hasGithubWorkflows: true,
|
|
21
|
-
hasGithubLevitateWorkflow: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
onFailure: console.error,
|
|
25
|
-
}
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
generate();
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const nodePlop = require('node-plop');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
async function generate() {
|
|
6
|
-
const plopFile = path.join(__dirname, '../dist/commands/generate.plopfile.js');
|
|
7
|
-
if (!fs.existsSync(plopFile)) {
|
|
8
|
-
console.error('Run build first');
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
const plop = await nodePlop(plopFile);
|
|
12
|
-
const generator = plop.getGenerator('create-plugin');
|
|
13
|
-
await generator.runActions(
|
|
14
|
-
{
|
|
15
|
-
pluginName: 'my-plugin',
|
|
16
|
-
orgName: 'my-org',
|
|
17
|
-
pluginDescription: 'Auto-generated panel',
|
|
18
|
-
pluginType: 'panel',
|
|
19
|
-
hasGithubWorkflows: true,
|
|
20
|
-
hasGithubLevitateWorkflow: true,
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
onFailure: console.error,
|
|
24
|
-
}
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
generate();
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const nodePlop = require('node-plop');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
|
|
5
|
-
async function generate() {
|
|
6
|
-
const plopFile = path.join(__dirname, '../dist/commands/generate.plopfile.js');
|
|
7
|
-
if (!fs.existsSync(plopFile)) {
|
|
8
|
-
console.error('Run build first');
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
const plop = await nodePlop(plopFile);
|
|
12
|
-
const generator = plop.getGenerator('create-plugin');
|
|
13
|
-
await generator.runActions(
|
|
14
|
-
{
|
|
15
|
-
pluginName: 'my-plugin',
|
|
16
|
-
orgName: 'my-org',
|
|
17
|
-
pluginDescription: 'Auto-generated scenes app',
|
|
18
|
-
pluginType: 'scenesapp',
|
|
19
|
-
hasBackend: false,
|
|
20
|
-
hasGithubWorkflows: true,
|
|
21
|
-
hasGithubLevitateWorkflow: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
onFailure: console.error,
|
|
25
|
-
}
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
generate();
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import glob from 'glob';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import type { ModifyActionConfig, NodePlopAPI } from 'plop';
|
|
5
|
-
import { EXTRA_TEMPLATE_VARIABLES, IS_DEV, PARTIALS_DIR, PLUGIN_TYPES, TEMPLATE_PATHS } from '../constants';
|
|
6
|
-
import { ifEq, normalizeId } from '../utils/utils.handlebars';
|
|
7
|
-
import { getExportPath } from '../utils/utils.path';
|
|
8
|
-
import { getPackageManagerInstallCmd, getPackageManagerFromUserAgent } from '../utils/utils.packageManager';
|
|
9
|
-
import { printGenerateSuccessMessage } from './generate-actions/print-success-message';
|
|
10
|
-
import { updateGoSdkAndModules } from './generate-actions/update-go-sdk-and-packages';
|
|
11
|
-
import { prettifyFiles } from './generate-actions/prettify-files';
|
|
12
|
-
import { CliArgs, TemplateData } from './types';
|
|
13
|
-
import { getExportFileName } from '../utils/utils.files';
|
|
14
|
-
import { getConfig } from '../utils/utils.config';
|
|
15
|
-
import { getVersion } from '../utils/utils.version';
|
|
16
|
-
|
|
17
|
-
// Plopfile API documentation: https://plopjs.com/documentation/#plopfile-api
|
|
18
|
-
export default function (plop: NodePlopAPI) {
|
|
19
|
-
plop.setHelper('if_eq', ifEq);
|
|
20
|
-
plop.setHelper('normalize_id', normalizeId);
|
|
21
|
-
|
|
22
|
-
plop.setActionType('printSuccessMessage', printGenerateSuccessMessage);
|
|
23
|
-
plop.setActionType('prettifyFiles', prettifyFiles);
|
|
24
|
-
plop.setActionType('updateGoSdkAndModules', updateGoSdkAndModules);
|
|
25
|
-
|
|
26
|
-
plop.setGenerator('create-plugin', {
|
|
27
|
-
description: 'used to scaffold a grafana plugin',
|
|
28
|
-
prompts: [
|
|
29
|
-
{
|
|
30
|
-
name: 'pluginName',
|
|
31
|
-
type: 'input',
|
|
32
|
-
message: 'What is going to be the name of your plugin?',
|
|
33
|
-
validate: (value: string) => {
|
|
34
|
-
if (/.+/.test(value)) {
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
return 'Plugin name is required';
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'orgName',
|
|
42
|
-
type: 'input',
|
|
43
|
-
message: 'What is the organization name of your plugin?',
|
|
44
|
-
validate: (value: string) => {
|
|
45
|
-
if (/.+/.test(value)) {
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
return 'Organization name is required';
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
name: 'pluginDescription',
|
|
53
|
-
type: 'input',
|
|
54
|
-
message: 'How would you describe your plugin?',
|
|
55
|
-
default: '',
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
name: 'pluginType',
|
|
59
|
-
type: 'list',
|
|
60
|
-
choices: [PLUGIN_TYPES.app, PLUGIN_TYPES.datasource, PLUGIN_TYPES.panel, PLUGIN_TYPES.scenes],
|
|
61
|
-
message: 'What type of plugin would you like?',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
name: 'hasBackend',
|
|
65
|
-
type: 'confirm',
|
|
66
|
-
message: 'Do you want a backend part of your plugin?',
|
|
67
|
-
default: false,
|
|
68
|
-
when: (answers: CliArgs) => answers.pluginType !== PLUGIN_TYPES.panel,
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'hasGithubWorkflows',
|
|
72
|
-
type: 'confirm',
|
|
73
|
-
message: 'Do you want to add Github CI and Release workflows?',
|
|
74
|
-
default: false,
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: 'hasGithubLevitateWorkflow',
|
|
78
|
-
type: 'confirm',
|
|
79
|
-
message: 'Do you want to add a Github workflow for automatically checking "Grafana API compatibility" on PRs?',
|
|
80
|
-
default: false,
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
actions: function ({
|
|
84
|
-
pluginName,
|
|
85
|
-
orgName,
|
|
86
|
-
pluginType,
|
|
87
|
-
hasBackend,
|
|
88
|
-
hasGithubWorkflows,
|
|
89
|
-
hasGithubLevitateWorkflow,
|
|
90
|
-
}: CliArgs) {
|
|
91
|
-
const { features } = getConfig();
|
|
92
|
-
const currentVersion = getVersion();
|
|
93
|
-
const exportPath = getExportPath(pluginName, orgName, pluginType);
|
|
94
|
-
const pluginId = normalizeId(pluginName, orgName, pluginType);
|
|
95
|
-
// Support the users package manager of choice.
|
|
96
|
-
const { packageManagerName, packageManagerVersion } = getPackageManagerFromUserAgent();
|
|
97
|
-
const packageManagerInstallCmd = getPackageManagerInstallCmd(packageManagerName);
|
|
98
|
-
const isAppType = pluginType === PLUGIN_TYPES.app || pluginType === PLUGIN_TYPES.scenes;
|
|
99
|
-
const templateData: TemplateData = {
|
|
100
|
-
pluginId,
|
|
101
|
-
packageManagerName,
|
|
102
|
-
packageManagerInstallCmd,
|
|
103
|
-
packageManagerVersion,
|
|
104
|
-
isAppType,
|
|
105
|
-
isNPM: packageManagerName === 'npm',
|
|
106
|
-
version: currentVersion,
|
|
107
|
-
bundleGrafanaUI: features.bundleGrafanaUI,
|
|
108
|
-
};
|
|
109
|
-
// Copy over files that are shared between plugins types
|
|
110
|
-
const commonActions = getActionsForTemplateFolder({
|
|
111
|
-
folderPath: TEMPLATE_PATHS.common,
|
|
112
|
-
exportPath,
|
|
113
|
-
templateData,
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Copy over files from the plugin type specific folder, e.g. "templates/app" for "app" plugins ("app" | "panel" | "datasource").
|
|
117
|
-
const pluginTypeSpecificActions = getActionsForTemplateFolder({
|
|
118
|
-
folderPath: TEMPLATE_PATHS[pluginType],
|
|
119
|
-
exportPath,
|
|
120
|
-
templateData,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
// Copy over backend-specific files (if selected)
|
|
124
|
-
const backendFolderPath = isAppType ? TEMPLATE_PATHS.backendApp : TEMPLATE_PATHS.backend;
|
|
125
|
-
const backendActions = hasBackend
|
|
126
|
-
? getActionsForTemplateFolder({ folderPath: backendFolderPath, exportPath, templateData })
|
|
127
|
-
: [];
|
|
128
|
-
|
|
129
|
-
// Common, pluginType and backend actions can contain different templates for the same destination.
|
|
130
|
-
// This filtering removes the duplicate file additions to prevent plop erroring and makes sure the
|
|
131
|
-
// correct template is scaffolded.
|
|
132
|
-
// Note that the order is reversed so backend > pluginType > common
|
|
133
|
-
const pluginActions = [...backendActions, ...pluginTypeSpecificActions, ...commonActions].reduce((acc, file) => {
|
|
134
|
-
const actionExists = acc.find((f) => f.path === file.path);
|
|
135
|
-
// return early to prevent multiple add type actions being added to the array
|
|
136
|
-
if (actionExists && actionExists.type === 'add' && file.type === 'add') {
|
|
137
|
-
return acc;
|
|
138
|
-
}
|
|
139
|
-
acc.push(file);
|
|
140
|
-
return acc;
|
|
141
|
-
}, []);
|
|
142
|
-
|
|
143
|
-
// Copy over Github workflow files (if selected)
|
|
144
|
-
const ciWorkflowActions = hasGithubWorkflows
|
|
145
|
-
? getActionsForTemplateFolder({
|
|
146
|
-
folderPath: TEMPLATE_PATHS.ciWorkflows,
|
|
147
|
-
exportPath,
|
|
148
|
-
templateData,
|
|
149
|
-
})
|
|
150
|
-
: [];
|
|
151
|
-
|
|
152
|
-
const isCompatibleWorkflowActions = hasGithubLevitateWorkflow
|
|
153
|
-
? getActionsForTemplateFolder({
|
|
154
|
-
folderPath: TEMPLATE_PATHS.isCompatibleWorkflow,
|
|
155
|
-
exportPath,
|
|
156
|
-
templateData,
|
|
157
|
-
})
|
|
158
|
-
: [];
|
|
159
|
-
|
|
160
|
-
// Replace conditional bits in the Readme files
|
|
161
|
-
const readmeActions = getActionsForReadme({ exportPath, templateData });
|
|
162
|
-
|
|
163
|
-
return [
|
|
164
|
-
...pluginActions,
|
|
165
|
-
...ciWorkflowActions,
|
|
166
|
-
...readmeActions,
|
|
167
|
-
...isCompatibleWorkflowActions,
|
|
168
|
-
{
|
|
169
|
-
type: 'updateGoSdkAndModules',
|
|
170
|
-
},
|
|
171
|
-
{ type: 'prettifyFiles' },
|
|
172
|
-
{
|
|
173
|
-
type: 'printSuccessMessage',
|
|
174
|
-
},
|
|
175
|
-
];
|
|
176
|
-
},
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function getActionsForReadme({
|
|
181
|
-
exportPath,
|
|
182
|
-
templateData,
|
|
183
|
-
}: {
|
|
184
|
-
exportPath: string;
|
|
185
|
-
templateData: TemplateData;
|
|
186
|
-
}): ModifyActionConfig[] {
|
|
187
|
-
return [
|
|
188
|
-
replacePatternWithTemplateInReadme(
|
|
189
|
-
'-- INSERT FRONTEND GETTING STARTED --',
|
|
190
|
-
'frontend-getting-started.md',
|
|
191
|
-
exportPath,
|
|
192
|
-
templateData
|
|
193
|
-
),
|
|
194
|
-
replacePatternWithTemplateInReadme(
|
|
195
|
-
'-- INSERT BACKEND GETTING STARTED --',
|
|
196
|
-
'backend-getting-started.md',
|
|
197
|
-
exportPath,
|
|
198
|
-
templateData
|
|
199
|
-
),
|
|
200
|
-
replacePatternWithTemplateInReadme(
|
|
201
|
-
'-- INSERT DISTRIBUTING YOUR PLUGIN --',
|
|
202
|
-
'distributing-your-plugin.md',
|
|
203
|
-
exportPath,
|
|
204
|
-
templateData
|
|
205
|
-
),
|
|
206
|
-
];
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function replacePatternWithTemplateInReadme(
|
|
210
|
-
pattern: string,
|
|
211
|
-
partialsFile: string,
|
|
212
|
-
exportPath: string,
|
|
213
|
-
templateData: TemplateData
|
|
214
|
-
): ModifyActionConfig {
|
|
215
|
-
return {
|
|
216
|
-
type: 'modify',
|
|
217
|
-
path: path.join(exportPath, 'README.md'),
|
|
218
|
-
pattern,
|
|
219
|
-
// @ts-ignore
|
|
220
|
-
template: undefined,
|
|
221
|
-
templateFile: path.join(PARTIALS_DIR, partialsFile),
|
|
222
|
-
data: {
|
|
223
|
-
...EXTRA_TEMPLATE_VARIABLES,
|
|
224
|
-
...templateData,
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// TODO<use Plop action `addMany` instead>
|
|
230
|
-
function getActionsForTemplateFolder({
|
|
231
|
-
folderPath,
|
|
232
|
-
exportPath,
|
|
233
|
-
templateData,
|
|
234
|
-
}: {
|
|
235
|
-
folderPath: string;
|
|
236
|
-
exportPath: string;
|
|
237
|
-
templateData: TemplateData;
|
|
238
|
-
}) {
|
|
239
|
-
let files = glob.sync(`${folderPath}/**`, { dot: true });
|
|
240
|
-
|
|
241
|
-
// The npmrc file is only useful for `pnpm` settings. We can remove it for other package managers.
|
|
242
|
-
if (templateData.packageManagerName !== 'pnpm') {
|
|
243
|
-
files = files.filter((file) => path.basename(file) !== 'npmrc');
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function getExportPath(f: string) {
|
|
247
|
-
return path.relative(folderPath, path.dirname(f));
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return files.filter(isFile).map((f) => ({
|
|
251
|
-
type: 'add',
|
|
252
|
-
templateFile: f,
|
|
253
|
-
// The target path where the compiled template is saved to
|
|
254
|
-
path: path.join(exportPath, getExportPath(f), getExportFileName(f)),
|
|
255
|
-
// Support overriding files in development for overriding "generated" plugins.
|
|
256
|
-
force: IS_DEV,
|
|
257
|
-
// We would still like to scaffold as many files as possible even if one fails
|
|
258
|
-
abortOnFail: false,
|
|
259
|
-
data: {
|
|
260
|
-
...EXTRA_TEMPLATE_VARIABLES,
|
|
261
|
-
...templateData,
|
|
262
|
-
},
|
|
263
|
-
}));
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function isFile(path: string) {
|
|
267
|
-
try {
|
|
268
|
-
return fs.lstatSync(path).isFile();
|
|
269
|
-
} catch (e) {
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
}
|