@grafana/create-plugin 0.2.0 → 0.3.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/CONTRIBUTING.md +45 -8
- package/README.md +25 -62
- package/dist/commands/generate.plopfile.js +2 -1
- package/dist/commands/update.command.js +1 -1
- package/dist/constants.js +6 -3
- package/dist/utils/tests/utils.handlebars.test.js +3 -3
- package/dist/utils/tests/utils.plugin.test.js +1 -1
- package/dist/utils/utils.handlebars.js +4 -2
- package/fixtures/test-template/src/plugin.json +35 -0
- package/jest.config.js +2 -17
- package/package.json +12 -24
- package/scripts/generate-app.js +24 -0
- package/scripts/generate-datasource.js +24 -0
- package/scripts/generate-panel.js +23 -0
- package/src/commands/generate.plopfile.ts +1 -0
- package/src/commands/update.command.ts +1 -1
- package/src/constants.ts +7 -2
- package/src/utils/tests/utils.handlebars.test.ts +3 -3
- package/src/utils/tests/utils.plugin.test.ts +2 -2
- package/src/utils/utils.handlebars.ts +5 -2
- package/templates/app/src/plugin.json +4 -1
- package/templates/backend/go.mod +55 -2
- package/templates/backend/go.sum +91 -4
- package/templates/common/.config/README.md +4 -4
- package/templates/common/.config/jest.config.js +5 -1
- package/templates/common/.config/tsconfig.json +8 -0
- package/templates/common/.config/webpack/webpack.config.ts +29 -16
- package/templates/common/.nvmrc +1 -1
- package/templates/common/jest.config.js +4 -0
- package/templates/common/package.json +8 -3
- package/templates/datasource/src/plugin.json +2 -2
- package/templates/github/ci/.github/workflows/ci.yml +11 -2
- package/templates/github/ci/.github/workflows/release.yml +3 -3
- package/templates/panel/src/plugin.json +1 -0
- package/tsconfig.json +4 -13
- package/.eslintrc +0 -6
- package/.github/workflows/create-release.yml +0 -49
- package/.github/workflows/npm-bump-version.yml +0 -51
- package/.github/workflows/test.yml +0 -31
- package/.prettierrc +0 -10
- package/docs/example.mp4 +0 -0
- package/templates/common/.config/webpack/tsconfig.webpack.json +0 -9
package/CONTRIBUTING.md
CHANGED
|
@@ -12,8 +12,8 @@ You need to have `npm` or `yarn` installed.
|
|
|
12
12
|
### Installing
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
git clone git@github.com:grafana/
|
|
16
|
-
cd
|
|
15
|
+
git clone git@github.com:grafana/plugin-tools.git
|
|
16
|
+
cd plugin-tools
|
|
17
17
|
yarn install
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -25,18 +25,55 @@ yarn install
|
|
|
25
25
|
|
|
26
26
|
### Folder structure
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
`@grafana/create-plugin` consists of the following folder structure:
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
├── src // Executable code
|
|
32
|
+
│ ├── bin // the entrypoint file
|
|
33
|
+
│ ├── commands // Code that runs commands
|
|
34
|
+
│ └── utils // Utilities used by commands
|
|
35
|
+
└── templates // Plop templates
|
|
36
|
+
├── _partials // Composable parts of a template
|
|
37
|
+
├── app // Templates specific to scaffolding an app plugin
|
|
38
|
+
├── backend // Templates specific to scaffolding backend plugin code
|
|
39
|
+
├── common // Common templates used by all plugin types (e.g. tooling config files)
|
|
40
|
+
├── datasource // Templates specific to scaffolding a datasource plugin
|
|
41
|
+
├── github // Templates for github workflows
|
|
42
|
+
└── panel // Templates specific to scaffolding a panel plugin
|
|
43
|
+
```
|
|
29
44
|
|
|
30
45
|
## Development
|
|
31
46
|
|
|
32
|
-
|
|
47
|
+
There are a collection of [commands](#commmands) to assist with developing `create-plugin`. Please read the main [contributing guide](../../CONTRIBUTING.md) before contributing any code changes to the project.
|
|
33
48
|
|
|
34
|
-
|
|
49
|
+
### Commmands
|
|
35
50
|
|
|
36
|
-
|
|
51
|
+
Below are the main commands used for developing `create-plugin`. They can be run by either `yarn workspace @grafana/create-plugin run <name_of_command>` or navigating to `packages/create-plugin` and running the command directly as detailed below.
|
|
37
52
|
|
|
38
|
-
|
|
53
|
+
```shell
|
|
54
|
+
yarn build # used to build @grafana/create-plugin
|
|
55
|
+
```
|
|
39
56
|
|
|
40
|
-
|
|
57
|
+
```shell
|
|
58
|
+
yarn dev # watches for changes to files and rebuilds @grafana/create-plugin automatically
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```shell
|
|
62
|
+
yarn dev-app # watches for changes and scaffolds an app plugin (in ./generated) for developing app configs
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```shell
|
|
66
|
+
yarn dev-panel # watches for changes and scaffolds an app plugin (in ./generated) for developing panel configs
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```shell
|
|
70
|
+
yarn dev-datasource # watches for changes and scaffolds an app plugin (in ./generated) for developing datasource configs
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Conventions
|
|
41
74
|
|
|
42
75
|
_Work in progress._
|
|
76
|
+
|
|
77
|
+
### Developing the templates
|
|
78
|
+
|
|
79
|
+
The templates are used by Plop to scaffold Grafana plugins. Whilst they appear to be the intended filetype they are infact treated as markdown by Plop when it runs. As such we need to be mindful of syntax and to [escape particular characters](https://handlebarsjs.com/guide/expressions.html#whitespace-control) where necessary. The [github/ci.yml](./templates/github/ci/.github/workflows/ci.yml) file is a good example of this.
|
package/README.md
CHANGED
|
@@ -4,11 +4,18 @@ Create Grafana plugins with ease.
|
|
|
4
4
|
|
|
5
5
|
**ToC**
|
|
6
6
|
|
|
7
|
-
- [
|
|
8
|
-
- [
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [
|
|
7
|
+
- [Grafana / Create Plugin](#grafana--create-plugin)
|
|
8
|
+
- [Create a new plugin](#create-a-new-plugin)
|
|
9
|
+
- [Quick overview](#quick-overview)
|
|
10
|
+
- [`yarn` (1.x)](#yarn-1x)
|
|
11
|
+
- [`yarn` (> 2.x)](#yarn--2x)
|
|
12
|
+
- [`npx`](#npx)
|
|
13
|
+
- [`npm`](#npm)
|
|
14
|
+
- [Migrate your existing plugin](#migrate-your-existing-plugin)
|
|
15
|
+
- [Things to check after migration](#things-to-check-after-migration)
|
|
16
|
+
- [Update your plugin build config](#update-your-plugin-build-config)
|
|
17
|
+
- [Customizing or extending the basic configs](#customizing-or-extending-the-basic-configs)
|
|
18
|
+
- [Contributing](#contributing)
|
|
12
19
|
|
|
13
20
|
**Links**
|
|
14
21
|
|
|
@@ -16,46 +23,39 @@ Create Grafana plugins with ease.
|
|
|
16
23
|
- [Plugin migration guide](https://grafana.com/docs/grafana/latest/developers/plugins/migration-guide/)
|
|
17
24
|
|
|
18
25
|
**`@grafana/create-plugin`** works on macOS, Windows and Linux.<br />
|
|
19
|
-
If something doesn
|
|
20
|
-
If you have questions or need help, please ask in [GitHub Discussions](https://github.com/grafana/
|
|
26
|
+
If something doesn't work, please [file an issue](https://github.com/grafana/plugin-tools/issues/new).<br />
|
|
27
|
+
If you have questions or need help, please ask in [GitHub Discussions](https://github.com/grafana/plugin-tools/discussions).
|
|
21
28
|
|
|
22
29
|
## Create a new plugin
|
|
23
30
|
|
|
24
31
|
### Quick overview
|
|
25
32
|
|
|
26
|
-
|
|
33
|
+
Run the command in the folder where you want to store your plugins. The new plugin will be scaffolded in a sub-directory of the folder where you run the command.
|
|
27
34
|
|
|
28
|
-
|
|
29
|
-
mkdir my-plugin && cd my-plugin
|
|
30
|
-
yarn create @grafana/plugin
|
|
31
|
-
yarn install
|
|
32
|
-
yarn dev
|
|
33
|
-
```
|
|
35
|
+
You can run the command with the package manager of your choice:
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
#### [`npx`](https://github.com/npm/npx)
|
|
37
|
+
#### [`yarn`](https://classic.yarnpkg.com/blog/2017/05/12/introducing-yarn/) (1.x)
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
|
-
|
|
40
|
+
yarn create @grafana/plugin
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
#### [`
|
|
43
|
+
#### [`yarn`](https://yarnpkg.com/cli/dlx) (> 2.x)
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
|
|
46
|
+
yarn dlx @grafana/create-plugin
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
#### [`
|
|
49
|
+
#### [`npx`](https://github.com/npm/npx)
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
|
|
52
|
+
npx @grafana/create-plugin
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
#### [`
|
|
55
|
+
#### [`npm`](https://docs.npmjs.com/cli/v7/commands/npm-init)
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
|
|
58
|
+
npm init @grafana/plugin
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
---
|
|
@@ -97,47 +97,10 @@ npx @grafana/create-plugin update
|
|
|
97
97
|
|
|
98
98
|
---
|
|
99
99
|
|
|
100
|
-
## Start developing your plugin
|
|
101
|
-
|
|
102
|
-
We have put together the following dev scripts for you, so you can start coding right away:
|
|
103
|
-
|
|
104
|
-
#### `yarn dev`
|
|
105
|
-
|
|
106
|
-
Starts the build in watch mode.
|
|
107
|
-
The build output (plugin bundle) is going to be exported to `./dist`.
|
|
108
|
-
|
|
109
|
-
#### `yarn build`
|
|
110
|
-
|
|
111
|
-
Creates a production build for your plugin.
|
|
112
|
-
The build output is going to be exported to `./dist`.
|
|
113
|
-
|
|
114
|
-
#### `yarn test`
|
|
115
|
-
|
|
116
|
-
Runs the tests under `./src` directory in watch mode.
|
|
117
|
-
Give your test files a `.test.tsx` or `.test.ts` extension.
|
|
118
|
-
|
|
119
|
-
#### `yarn test:ci`
|
|
120
|
-
|
|
121
|
-
Runs the tests and returns with either a zero or a non-zero exit status.
|
|
122
|
-
|
|
123
|
-
#### `yarn typecheck`
|
|
124
|
-
|
|
125
|
-
Runs the Typescript compiler against the codebase in a dry-run mode to highlight any type errors or warnings.
|
|
126
|
-
|
|
127
|
-
#### `yarn lint`
|
|
128
|
-
|
|
129
|
-
Runs ESLint against the codebase.
|
|
130
|
-
|
|
131
|
-
#### `yarn lint:fix`
|
|
132
|
-
|
|
133
|
-
Runs ESLint against the codebase and attempts to fix the simpler errors.
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
100
|
## Customizing or extending the basic configs
|
|
138
101
|
|
|
139
102
|
You can read more about customizing or extending the basic configuration [here](templates/common/.config/README.md)
|
|
140
103
|
|
|
141
104
|
## Contributing
|
|
142
105
|
|
|
143
|
-
We are always grateful for
|
|
106
|
+
We are always grateful for contributions! See the [CONTRIBUTING.md](../CONTRIBUTING.md) for more information.
|
|
@@ -61,7 +61,8 @@ function default_1(plop) {
|
|
|
61
61
|
name: 'hasBackend',
|
|
62
62
|
type: 'confirm',
|
|
63
63
|
message: 'Do you want a backend part of your plugin?',
|
|
64
|
-
"default": false
|
|
64
|
+
"default": false,
|
|
65
|
+
when: function (answers) { return answers.pluginType !== constants_1.PLUGIN_TYPES.panel; }
|
|
65
66
|
},
|
|
66
67
|
{
|
|
67
68
|
name: 'hasGithubWorkflows',
|
|
@@ -48,7 +48,7 @@ var update = function () { return __awaiter(void 0, void 0, void 0, function ()
|
|
|
48
48
|
case 0:
|
|
49
49
|
_a.trys.push([0, 5, , 6]);
|
|
50
50
|
(0, utils_console_1.printMessage)(constants_1.TEXT.updateCommandWarning);
|
|
51
|
-
return [4, (0, utils_console_1.confirmPrompt)(constants_1.TEXT.
|
|
51
|
+
return [4, (0, utils_console_1.confirmPrompt)(constants_1.TEXT.updateConfigPrompt)];
|
|
52
52
|
case 1:
|
|
53
53
|
if (_a.sent()) {
|
|
54
54
|
(0, utils_templates_1.compileTemplateFiles)(constants_1.UDPATE_CONFIG.filesToOverride, (0, utils_templates_1.getTemplateData)());
|
package/dist/constants.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
exports.__esModule = true;
|
|
6
|
-
exports.TEXT = exports.UDPATE_CONFIG = exports.MIGRATION_CONFIG = exports.EXTRA_TEMPLATE_VARIABLES = exports.PLUGIN_TYPES = exports.TEMPLATE_PATHS = exports.PARTIALS_DIR = exports.TEMPLATES_DIR = exports.DIST_DIR = exports.EXPORT_PATH_PREFIX = exports.DEV_EXPORT_DIR = exports.IS_DEV = void 0;
|
|
6
|
+
exports.TEXT = exports.UDPATE_CONFIG = exports.MIGRATION_CONFIG = exports.EXTRA_TEMPLATE_VARIABLES = exports.PLUGIN_TYPES = exports.TEMPLATE_PATHS = exports.FIXTURES_PATH = exports.PARTIALS_DIR = exports.TEMPLATES_DIR = exports.DIST_DIR = exports.EXPORT_PATH_PREFIX = exports.DEV_EXPORT_DIR = exports.IS_DEV = void 0;
|
|
7
7
|
var path_1 = __importDefault(require("path"));
|
|
8
8
|
exports.IS_DEV = process.env.CREATE_PLUGIN_DEV !== undefined;
|
|
9
9
|
exports.DEV_EXPORT_DIR = path_1["default"].join(__dirname, '..', 'generated');
|
|
@@ -11,6 +11,7 @@ exports.EXPORT_PATH_PREFIX = exports.IS_DEV ? exports.DEV_EXPORT_DIR : process.c
|
|
|
11
11
|
exports.DIST_DIR = path_1["default"].join(__dirname, 'dist');
|
|
12
12
|
exports.TEMPLATES_DIR = path_1["default"].join(__dirname, '..', 'templates');
|
|
13
13
|
exports.PARTIALS_DIR = path_1["default"].join(exports.TEMPLATES_DIR, '_partials');
|
|
14
|
+
exports.FIXTURES_PATH = path_1["default"].join(__dirname, '..', 'fixtures');
|
|
14
15
|
exports.TEMPLATE_PATHS = {
|
|
15
16
|
app: path_1["default"].join(exports.TEMPLATES_DIR, 'app'),
|
|
16
17
|
backend: path_1["default"].join(exports.TEMPLATES_DIR, 'backend'),
|
|
@@ -25,6 +26,7 @@ var PLUGIN_TYPES;
|
|
|
25
26
|
PLUGIN_TYPES["app"] = "app";
|
|
26
27
|
PLUGIN_TYPES["panel"] = "panel";
|
|
27
28
|
PLUGIN_TYPES["datasource"] = "datasource";
|
|
29
|
+
PLUGIN_TYPES["secretsmanager"] = "secretsmanager";
|
|
28
30
|
})(PLUGIN_TYPES = exports.PLUGIN_TYPES || (exports.PLUGIN_TYPES = {}));
|
|
29
31
|
exports.EXTRA_TEMPLATE_VARIABLES = {
|
|
30
32
|
grafanaVersion: '9.1.2'
|
|
@@ -64,11 +66,12 @@ exports.TEXT = {
|
|
|
64
66
|
removeNpmDependenciesPrompt: '**Would you like to remove the following possibly unnecessary NPM dependencies?**',
|
|
65
67
|
removeNpmDependenciesSuccess: 'Unnecessary NPM dependencies removed successfully.',
|
|
66
68
|
removeNpmDependenciesAborted: 'No NPM dependencies have been removed.',
|
|
69
|
+
updateConfigPrompt: "**Would you like to update the project's configuration?**",
|
|
67
70
|
updateNpmScriptsPrompt: '**Would you like to update the `{ scripts }` in your `package.json`?**',
|
|
68
71
|
updateNpmScriptsSuccess: 'NPM scripts updated successfully.',
|
|
69
72
|
updateNpmScriptsAborted: 'No NPM scripts have been added or updated.',
|
|
70
73
|
migrationCommandWarning: '**⚠️ Warning!**\nThis is going to change files in your current project to make it up-to-date with the latest plugin configuration.\nPlease make sure that you have backed up your changes.',
|
|
71
|
-
migrationCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/
|
|
74
|
+
migrationCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/plugin-tools.',
|
|
72
75
|
updateCommandWarning: '**⚠️ Warning!**\nThis is going to update files under the `.config/` folder.\nMake sure to commit your changes before running this script.',
|
|
73
|
-
updateCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/
|
|
76
|
+
updateCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/plugin-tools.'
|
|
74
77
|
};
|
|
@@ -8,19 +8,19 @@ describe('Handlebars helpers', function () {
|
|
|
8
8
|
var pluginName = 'my-plugin';
|
|
9
9
|
var orgName = 'my-org';
|
|
10
10
|
var actual = (0, utils_handlebars_1.normalizeId)(pluginName, orgName, type);
|
|
11
|
-
expect(actual).toEqual("
|
|
11
|
+
expect(actual).toEqual("myorg-myplugin-".concat(type));
|
|
12
12
|
});
|
|
13
13
|
test.each([constants_1.PLUGIN_TYPES.app, constants_1.PLUGIN_TYPES.datasource, constants_1.PLUGIN_TYPES.panel])('should not duplicate the type if it is already present', function (type) {
|
|
14
14
|
var pluginName = "my-plugin-".concat(type);
|
|
15
15
|
var orgName = 'my-org';
|
|
16
16
|
var actual = (0, utils_handlebars_1.normalizeId)(pluginName, orgName, type);
|
|
17
|
-
expect(actual).toEqual("
|
|
17
|
+
expect(actual).toEqual("myorg-myplugin-".concat(type));
|
|
18
18
|
});
|
|
19
19
|
test.each([constants_1.PLUGIN_TYPES.app, constants_1.PLUGIN_TYPES.datasource, constants_1.PLUGIN_TYPES.panel])('should not duplicate the type if it is already present (no dash before type)', function (type) {
|
|
20
20
|
var pluginName = "my-plugin".concat(type);
|
|
21
21
|
var orgName = 'my-org';
|
|
22
22
|
var actual = (0, utils_handlebars_1.normalizeId)(pluginName, orgName, type);
|
|
23
|
-
expect(actual).toEqual("
|
|
23
|
+
expect(actual).toEqual("myorg-myplugin-".concat(type));
|
|
24
24
|
});
|
|
25
25
|
});
|
|
26
26
|
});
|
|
@@ -5,7 +5,7 @@ var utils_plugin_1 = require("../utils.plugin");
|
|
|
5
5
|
describe('Utils / Plugins', function () {
|
|
6
6
|
describe('getPluginJson()', function () {
|
|
7
7
|
test('should return the parsed plugin JSON if the file exits', function () {
|
|
8
|
-
var srcDir = "".concat(constants_1.
|
|
8
|
+
var srcDir = "".concat(constants_1.FIXTURES_PATH, "/test-template/src");
|
|
9
9
|
var pluginJson = (0, utils_plugin_1.getPluginJson)(srcDir);
|
|
10
10
|
expect(pluginJson).toBeDefined();
|
|
11
11
|
expect(pluginJson.type).toBe('app');
|
|
@@ -39,8 +39,10 @@ var ifEq = function (a, b, options) {
|
|
|
39
39
|
exports.ifEq = ifEq;
|
|
40
40
|
var normalizeId = function (pluginName, orgName, type) {
|
|
41
41
|
var re = new RegExp("-?".concat(type, "$"), 'i');
|
|
42
|
-
var
|
|
43
|
-
|
|
42
|
+
var nameRegex = new RegExp('[^0-9a-z]', 'g');
|
|
43
|
+
var newPluginName = pluginName.replace(re, '').replace(nameRegex, '');
|
|
44
|
+
var newOrgName = orgName.replace(nameRegex, '');
|
|
45
|
+
return changeCase.lowerCase(newOrgName) + '-' + changeCase.lowerCase(newPluginName) + "-".concat(type);
|
|
44
46
|
};
|
|
45
47
|
exports.normalizeId = normalizeId;
|
|
46
48
|
function registerHandlebarsHelpers() {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/grafana/grafana/master/docs/sources/developers/plugins/plugin.schema.json",
|
|
3
|
+
"type": "app",
|
|
4
|
+
"name": "{{ titleCase pluginName }}",
|
|
5
|
+
"id": "{{ normalize_id pluginName orgName 'app' }}",
|
|
6
|
+
"backend": true,
|
|
7
|
+
"executable": "gpx_{{ snakeCase pluginName }}",
|
|
8
|
+
"info": {
|
|
9
|
+
"description": "{{ sentenceCase pluginDescription }}",
|
|
10
|
+
"author": {
|
|
11
|
+
"name": "{{ sentenceCase orgName }}"
|
|
12
|
+
},
|
|
13
|
+
"logos": {
|
|
14
|
+
"small": "img/logo.svg",
|
|
15
|
+
"large": "img/logo.svg"
|
|
16
|
+
},
|
|
17
|
+
"screenshots": [],
|
|
18
|
+
"version": "%VERSION%",
|
|
19
|
+
"updated": "%TODAY%"
|
|
20
|
+
},
|
|
21
|
+
"includes": [
|
|
22
|
+
{
|
|
23
|
+
"type": "page",
|
|
24
|
+
"name": "Default",
|
|
25
|
+
"path": "/a/%PLUGIN_ID%",
|
|
26
|
+
"role": "Admin",
|
|
27
|
+
"addToNav": true,
|
|
28
|
+
"defaultNav": true
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"grafanaDependency": ">={{ grafanaVersion }}",
|
|
33
|
+
"plugins": []
|
|
34
|
+
}
|
|
35
|
+
}
|
package/jest.config.js
CHANGED
|
@@ -1,20 +1,5 @@
|
|
|
1
|
+
const sharedConfig = require('../../jest.config.base');
|
|
1
2
|
module.exports = {
|
|
2
|
-
|
|
3
|
-
transform: {
|
|
4
|
-
'^.+\\.(t|j)sx?$': [
|
|
5
|
-
'@swc/jest',
|
|
6
|
-
{
|
|
7
|
-
sourceMaps: true,
|
|
8
|
-
jsc: {
|
|
9
|
-
parser: {
|
|
10
|
-
syntax: 'typescript',
|
|
11
|
-
tsx: true,
|
|
12
|
-
decorators: false,
|
|
13
|
-
dynamicImport: true,
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
},
|
|
3
|
+
...sharedConfig,
|
|
19
4
|
modulePathIgnorePatterns: ['<rootDir>/templates/'],
|
|
20
5
|
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafana/create-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"main": "index.js",
|
|
5
|
-
"repository":
|
|
5
|
+
"repository": {
|
|
6
|
+
"directory": "packages/create-plugin",
|
|
7
|
+
"url": "git@github.com:grafana/plugin-tools.git"
|
|
8
|
+
},
|
|
6
9
|
"author": "Grafana",
|
|
7
10
|
"license": "Apache-2.0",
|
|
8
11
|
"bin": "./dist/bin/run.js",
|
|
@@ -14,45 +17,30 @@
|
|
|
14
17
|
"dev-app": "CREATE_PLUGIN_DEV=true nodemon --exec 'yarn generate-app'",
|
|
15
18
|
"dev-panel": "CREATE_PLUGIN_DEV=true nodemon --exec 'yarn generate-panel'",
|
|
16
19
|
"dev-datasource": "CREATE_PLUGIN_DEV=true nodemon --exec 'yarn generate-datasource'",
|
|
17
|
-
"generate-app": "tsc && yarn clean-generated && CREATE_PLUGIN_DEV=true node ./
|
|
18
|
-
"generate-panel": "tsc && yarn clean-generated && CREATE_PLUGIN_DEV=true node ./
|
|
19
|
-
"generate-datasource": "tsc && yarn clean-generated && CREATE_PLUGIN_DEV=true node ./
|
|
20
|
-
"lint": "eslint --cache --
|
|
20
|
+
"generate-app": "tsc && yarn clean-generated && CREATE_PLUGIN_DEV=true node ./scripts/generate-app.js",
|
|
21
|
+
"generate-panel": "tsc && yarn clean-generated && CREATE_PLUGIN_DEV=true node ./scripts/generate-panel.js",
|
|
22
|
+
"generate-datasource": "tsc && yarn clean-generated && CREATE_PLUGIN_DEV=true node ./scripts/generate-datasource.js",
|
|
23
|
+
"lint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./src",
|
|
21
24
|
"lint:fix": "yarn lint --fix",
|
|
22
|
-
"test": "jest
|
|
25
|
+
"test": "jest",
|
|
23
26
|
"typecheck": "tsc --noEmit"
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
|
-
"@grafana/tsconfig": "^1.2.0-rc1",
|
|
27
|
-
"@swc/core": "^1.2.162",
|
|
28
29
|
"@types/minimist": "^1.2.2",
|
|
29
30
|
"@types/mkdirp": "^1.0.2",
|
|
30
31
|
"@types/semver": "^7.3.9",
|
|
31
32
|
"enquirer": "^2.3.6",
|
|
32
33
|
"glob": "^7.1.7",
|
|
33
|
-
"jest": "^27.5.1",
|
|
34
|
-
"marked-terminal": "^5.1.1",
|
|
35
34
|
"marked": "^4.0.12",
|
|
35
|
+
"marked-terminal": "^5.1.1",
|
|
36
36
|
"mkdirp": "^1.0.4",
|
|
37
37
|
"plop": "^2.7.4",
|
|
38
38
|
"semver": "^7.3.5"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@grafana/eslint-config": "^2.5.0",
|
|
42
|
-
"@swc/jest": "^0.2.20",
|
|
43
41
|
"@types/glob": "^7.0.0",
|
|
44
|
-
"@types/jest": "^27.4.1",
|
|
45
|
-
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
|
46
|
-
"@typescript-eslint/parser": "^4.33.0",
|
|
47
|
-
"eslint": "^7.32.0",
|
|
48
|
-
"eslint-config-prettier": "^8.3.0",
|
|
49
|
-
"eslint-plugin-jsdoc": "^36.1.0",
|
|
50
|
-
"eslint-plugin-prettier": "^4.0.0",
|
|
51
42
|
"eslint-plugin-react": "^7.26.1",
|
|
52
|
-
"eslint-plugin-react-hooks": "^4.2.0"
|
|
53
|
-
"nodemon": "^2.0.13",
|
|
54
|
-
"tsc-watch": "^4.5.0",
|
|
55
|
-
"typescript": "^4.4.3"
|
|
43
|
+
"eslint-plugin-react-hooks": "^4.2.0"
|
|
56
44
|
},
|
|
57
45
|
"nodemonConfig": {
|
|
58
46
|
"watch": [
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const nodePlop = require('node-plop');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
async function generatePanel() {
|
|
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
|
+
pluginName: 'my-plugin',
|
|
15
|
+
orgName: 'my-org',
|
|
16
|
+
pluginDescription: 'Auto-generated app',
|
|
17
|
+
pluginType: 'app',
|
|
18
|
+
hasBackend: false,
|
|
19
|
+
hasGithubWorkflows: true,
|
|
20
|
+
hasGithubLevitateWorkflow: true,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
generatePanel();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const nodePlop = require('node-plop');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
async function generatePanel() {
|
|
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
|
+
pluginName: 'my-plugin',
|
|
15
|
+
orgName: 'my-org',
|
|
16
|
+
pluginDescription: 'Auto-generated datasource',
|
|
17
|
+
pluginType: 'datasource',
|
|
18
|
+
hasBackend: true,
|
|
19
|
+
hasGithubWorkflows: true,
|
|
20
|
+
hasGithubLevitateWorkflow: true,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
generatePanel();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const nodePlop = require('node-plop');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
async function generatePanel() {
|
|
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
|
+
pluginName: 'my-plugin',
|
|
15
|
+
orgName: 'my-org',
|
|
16
|
+
pluginDescription: 'Auto-generated panel',
|
|
17
|
+
pluginType: 'panel',
|
|
18
|
+
hasGithubWorkflows: true,
|
|
19
|
+
hasGithubLevitateWorkflow: true,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
generatePanel();
|
|
@@ -16,7 +16,7 @@ export const update = async () => {
|
|
|
16
16
|
|
|
17
17
|
// 1. Add / update configuration files
|
|
18
18
|
// -----------------------------------
|
|
19
|
-
if (await confirmPrompt(TEXT.
|
|
19
|
+
if (await confirmPrompt(TEXT.updateConfigPrompt)) {
|
|
20
20
|
compileTemplateFiles(UDPATE_CONFIG.filesToOverride, getTemplateData());
|
|
21
21
|
printSuccessMessage(TEXT.overrideFilesSuccess);
|
|
22
22
|
} else {
|
package/src/constants.ts
CHANGED
|
@@ -14,6 +14,8 @@ export const TEMPLATES_DIR = path.join(__dirname, '..', 'templates');
|
|
|
14
14
|
// (they won't be copied over to the generated folder as they are)
|
|
15
15
|
export const PARTIALS_DIR = path.join(TEMPLATES_DIR, '_partials');
|
|
16
16
|
|
|
17
|
+
export const FIXTURES_PATH = path.join(__dirname, '..', 'fixtures');
|
|
18
|
+
|
|
17
19
|
export const TEMPLATE_PATHS: Record<string, string> = {
|
|
18
20
|
app: path.join(TEMPLATES_DIR, 'app'),
|
|
19
21
|
backend: path.join(TEMPLATES_DIR, 'backend'),
|
|
@@ -28,6 +30,7 @@ export enum PLUGIN_TYPES {
|
|
|
28
30
|
app = 'app',
|
|
29
31
|
panel = 'panel',
|
|
30
32
|
datasource = 'datasource',
|
|
33
|
+
secretsmanager = 'secretsmanager',
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
// This gets merged into variables coming from user prompts (when using Plop) or any other dynamic variables,
|
|
@@ -87,13 +90,15 @@ export const TEXT = {
|
|
|
87
90
|
removeNpmDependenciesSuccess: 'Unnecessary NPM dependencies removed successfully.',
|
|
88
91
|
removeNpmDependenciesAborted: 'No NPM dependencies have been removed.',
|
|
89
92
|
|
|
93
|
+
updateConfigPrompt: "**Would you like to update the project's configuration?**",
|
|
94
|
+
|
|
90
95
|
updateNpmScriptsPrompt: '**Would you like to update the `{ scripts }` in your `package.json`?**',
|
|
91
96
|
updateNpmScriptsSuccess: 'NPM scripts updated successfully.',
|
|
92
97
|
updateNpmScriptsAborted: 'No NPM scripts have been added or updated.',
|
|
93
98
|
|
|
94
99
|
migrationCommandWarning: '**⚠️ Warning!**\nThis is going to change files in your current project to make it up-to-date with the latest plugin configuration.\nPlease make sure that you have backed up your changes.',
|
|
95
|
-
migrationCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/
|
|
100
|
+
migrationCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/plugin-tools.',
|
|
96
101
|
|
|
97
102
|
updateCommandWarning: '**⚠️ Warning!**\nThis is going to update files under the `.config/` folder.\nMake sure to commit your changes before running this script.',
|
|
98
|
-
updateCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/
|
|
103
|
+
updateCommandSuccess: '**Done.**\nIf you have any questions please open an issue/discussion in https://github.com/grafana/plugin-tools.',
|
|
99
104
|
}
|
|
@@ -9,7 +9,7 @@ describe('Handlebars helpers', () => {
|
|
|
9
9
|
const pluginName = 'my-plugin';
|
|
10
10
|
const orgName = 'my-org';
|
|
11
11
|
const actual = normalizeId(pluginName, orgName, type);
|
|
12
|
-
expect(actual).toEqual(`
|
|
12
|
+
expect(actual).toEqual(`myorg-myplugin-${type}`);
|
|
13
13
|
}
|
|
14
14
|
);
|
|
15
15
|
test.each([PLUGIN_TYPES.app, PLUGIN_TYPES.datasource, PLUGIN_TYPES.panel])(
|
|
@@ -18,7 +18,7 @@ describe('Handlebars helpers', () => {
|
|
|
18
18
|
const pluginName = `my-plugin-${type}`;
|
|
19
19
|
const orgName = 'my-org';
|
|
20
20
|
const actual = normalizeId(pluginName, orgName, type);
|
|
21
|
-
expect(actual).toEqual(`
|
|
21
|
+
expect(actual).toEqual(`myorg-myplugin-${type}`);
|
|
22
22
|
}
|
|
23
23
|
);
|
|
24
24
|
|
|
@@ -28,7 +28,7 @@ describe('Handlebars helpers', () => {
|
|
|
28
28
|
const pluginName = `my-plugin${type}`;
|
|
29
29
|
const orgName = 'my-org';
|
|
30
30
|
const actual = normalizeId(pluginName, orgName, type);
|
|
31
|
-
expect(actual).toEqual(`
|
|
31
|
+
expect(actual).toEqual(`myorg-myplugin-${type}`);
|
|
32
32
|
}
|
|
33
33
|
);
|
|
34
34
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { TEMPLATE_PATHS } from '../../constants';
|
|
1
|
+
import { FIXTURES_PATH, TEMPLATE_PATHS } from '../../constants';
|
|
2
2
|
import { getPluginJson } from '../utils.plugin';
|
|
3
3
|
|
|
4
4
|
describe('Utils / Plugins', () => {
|
|
5
5
|
describe('getPluginJson()', () => {
|
|
6
6
|
test('should return the parsed plugin JSON if the file exits', () => {
|
|
7
|
-
const srcDir = `${
|
|
7
|
+
const srcDir = `${FIXTURES_PATH}/test-template/src`;
|
|
8
8
|
const pluginJson = getPluginJson(srcDir);
|
|
9
9
|
|
|
10
10
|
expect(pluginJson).toBeDefined();
|
|
@@ -12,8 +12,11 @@ export const ifEq = (a: any, b: any, options: HelperOptions) => {
|
|
|
12
12
|
|
|
13
13
|
export const normalizeId = (pluginName: string, orgName: string, type: PLUGIN_TYPES) => {
|
|
14
14
|
const re = new RegExp(`-?${type}$`, 'i');
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
const nameRegex = new RegExp('[^0-9a-z]', 'g');
|
|
16
|
+
|
|
17
|
+
const newPluginName = pluginName.replace(re, '').replace(nameRegex, '');
|
|
18
|
+
const newOrgName = orgName.replace(nameRegex, '');
|
|
19
|
+
return changeCase.lowerCase(newOrgName) + '-' + changeCase.lowerCase(newPluginName) + `-${type}`;
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
// Needed when we are rendering the templates outside of the context of Plop but still would like to support the same helpers
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/grafana/grafana/master/docs/sources/developers/plugins/plugin.schema.json",
|
|
3
3
|
"type": "app",
|
|
4
4
|
"name": "{{ titleCase pluginName }}",
|
|
5
|
-
"id": "{{ normalize_id pluginName orgName 'app' }}",
|
|
5
|
+
"id": "{{ normalize_id pluginName orgName 'app' }}",{{#if hasBackend}}
|
|
6
|
+
"backend": true,
|
|
7
|
+
"executable": "gpx_{{ snakeCase pluginName }}",{{/if}}
|
|
6
8
|
"info": {
|
|
9
|
+
"keywords": ["app"],
|
|
7
10
|
"description": "{{ sentenceCase pluginDescription }}",
|
|
8
11
|
"author": {
|
|
9
12
|
"name": "{{ sentenceCase orgName }}"
|