@grafana/create-plugin 6.2.0-canary.2233.19133609453.0 → 6.2.0-canary.2283.19173715977.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 +23 -0
- package/CONTRIBUTING.md +3 -0
- package/dist/bin/run.js +1 -3
- package/dist/commands/update.command.js +1 -1
- package/dist/{codemods → migrations}/context.js +2 -3
- package/dist/{codemods/migrations → migrations}/manager.js +7 -8
- package/dist/{codemods/migrations → migrations}/migrations.js +6 -3
- package/dist/{codemods/migrations → migrations}/scripts/003-update-eslint-deprecation-rule.js +1 -1
- package/dist/{codemods/migrations → migrations}/scripts/004-eslint9-flat-config.js +1 -2
- package/dist/migrations/scripts/005-react-18-3.js +20 -0
- package/dist/{codemods → migrations}/utils.js +22 -5
- package/dist/utils/utils.config.js +1 -16
- package/package.json +2 -2
- package/src/bin/run.ts +1 -2
- package/src/commands/index.ts +0 -1
- package/src/commands/update.command.ts +1 -1
- package/src/{codemods → migrations}/context.test.ts +10 -10
- package/src/{codemods → migrations}/context.ts +2 -4
- package/src/{codemods/migrations → migrations}/manager.test.ts +10 -15
- package/src/{codemods/migrations → migrations}/manager.ts +9 -10
- package/src/{codemods/migrations → migrations}/migrations.ts +8 -3
- package/src/{codemods/migrations → migrations}/scripts/001-update-grafana-compose-extend.test.ts +1 -1
- package/src/{codemods/migrations → migrations}/scripts/001-update-grafana-compose-extend.ts +1 -1
- package/src/{codemods/migrations → migrations}/scripts/002-update-is-compatible-workflow.test.ts +1 -1
- package/src/{codemods/migrations → migrations}/scripts/002-update-is-compatible-workflow.ts +1 -1
- package/src/{codemods/migrations → migrations}/scripts/003-update-eslint-deprecation-rule.test.ts +1 -1
- package/src/{codemods/migrations → migrations}/scripts/003-update-eslint-deprecation-rule.ts +2 -2
- package/src/{codemods/migrations → migrations}/scripts/004-eslint9-flat-config.test.ts +1 -1
- package/src/{codemods/migrations → migrations}/scripts/004-eslint9-flat-config.ts +2 -3
- package/src/migrations/scripts/005-react-18-3.test.ts +147 -0
- package/src/migrations/scripts/005-react-18-3.ts +19 -0
- package/src/{codemods/migrations → migrations}/scripts/example-migration.test.ts +1 -1
- package/src/{codemods/migrations → migrations}/scripts/example-migration.ts +1 -1
- package/src/{codemods/migrations → migrations}/utils.test.ts +4 -4
- package/src/{codemods → migrations}/utils.ts +33 -37
- package/src/utils/utils.config.ts +1 -28
- package/templates/common/_package.json +5 -3
- package/templates/github/workflows/cp-update.yml +8 -13
- package/dist/codemods/additions/additions.js +0 -11
- package/dist/codemods/additions/manager.js +0 -115
- package/dist/codemods/additions/scripts/example-addition.js +0 -61
- package/dist/codemods/additions/utils.js +0 -10
- package/dist/codemods/migrations/utils.js +0 -10
- package/dist/commands/add.command.js +0 -86
- package/src/codemods/additions/additions.ts +0 -23
- package/src/codemods/additions/manager.ts +0 -145
- package/src/codemods/additions/scripts/example-addition.test.ts +0 -111
- package/src/codemods/additions/scripts/example-addition.ts +0 -79
- package/src/codemods/additions/utils.ts +0 -12
- package/src/codemods/migrations/utils.ts +0 -12
- package/src/codemods/types.ts +0 -21
- package/src/commands/add.command.ts +0 -97
- /package/dist/{codemods/migrations → migrations}/scripts/001-update-grafana-compose-extend.js +0 -0
- /package/dist/{codemods/migrations → migrations}/scripts/002-update-is-compatible-workflow.js +0 -0
- /package/dist/{codemods/migrations → migrations}/scripts/example-migration.js +0 -0
- /package/src/{codemods/migrations → migrations}/fixtures/foo/bar.ts +0 -0
- /package/src/{codemods/migrations → migrations}/fixtures/foo/baz.ts +0 -0
- /package/src/{codemods/migrations → migrations}/fixtures/migrations.ts +0 -0
- /package/src/{codemods/migrations → migrations}/migrations.test.ts +0 -0
- /package/src/{codemods → migrations}/test-utils.ts +0 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { Context } from '../context.js';
|
|
3
|
+
import migrate from './005-react-18-3.js';
|
|
4
|
+
|
|
5
|
+
describe('005-react-18-3', () => {
|
|
6
|
+
it('should not modify anything if package.json does not exist', async () => {
|
|
7
|
+
const context = new Context('/virtual');
|
|
8
|
+
await migrate(context);
|
|
9
|
+
expect(context.listChanges()).toEqual({});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should not modify anything if there are no React dependencies', async () => {
|
|
13
|
+
const context = new Context('/virtual');
|
|
14
|
+
context.addFile(
|
|
15
|
+
'./package.json',
|
|
16
|
+
JSON.stringify({
|
|
17
|
+
dependencies: {
|
|
18
|
+
lodash: '^4.17.21',
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
);
|
|
22
|
+
const initialChanges = context.listChanges();
|
|
23
|
+
await migrate(context);
|
|
24
|
+
expect(context.listChanges()).toEqual(initialChanges);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should not update React if version is below 18.0.0', async () => {
|
|
28
|
+
const context = new Context('/virtual');
|
|
29
|
+
const packageJson = {
|
|
30
|
+
dependencies: {
|
|
31
|
+
react: '^17.0.2',
|
|
32
|
+
'react-dom': '^17.0.2',
|
|
33
|
+
},
|
|
34
|
+
devDependencies: {
|
|
35
|
+
'@types/react': '^17.0.0',
|
|
36
|
+
'@types/react-dom': '^17.0.0',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
context.addFile('./package.json', JSON.stringify(packageJson, null, 2));
|
|
40
|
+
const initialPackageJson = context.getFile('./package.json');
|
|
41
|
+
|
|
42
|
+
await migrate(context);
|
|
43
|
+
|
|
44
|
+
expect(context.getFile('./package.json')).toBe(initialPackageJson);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('should not downgrade React 19.0.0 to 18.3.1', async () => {
|
|
48
|
+
const context = new Context('/virtual');
|
|
49
|
+
const packageJson = {
|
|
50
|
+
dependencies: {
|
|
51
|
+
react: '^19.0.0',
|
|
52
|
+
'react-dom': '^19.0.0',
|
|
53
|
+
},
|
|
54
|
+
devDependencies: {
|
|
55
|
+
'@types/react': '^19.0.0',
|
|
56
|
+
'@types/react-dom': '^19.0.0',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
context.addFile('./package.json', JSON.stringify(packageJson, null, 2));
|
|
60
|
+
|
|
61
|
+
await migrate(context);
|
|
62
|
+
|
|
63
|
+
const updatedPackageJson = JSON.parse(context.getFile('./package.json') || '{}');
|
|
64
|
+
expect(updatedPackageJson.dependencies.react).toBe('^19.0.0');
|
|
65
|
+
expect(updatedPackageJson.dependencies['react-dom']).toBe('^19.0.0');
|
|
66
|
+
expect(updatedPackageJson.devDependencies['@types/react']).toBe('^19.0.0');
|
|
67
|
+
expect(updatedPackageJson.devDependencies['@types/react-dom']).toBe('^19.0.0');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should update React 18.0.0 to 18.3.1', async () => {
|
|
71
|
+
const context = new Context('/virtual');
|
|
72
|
+
context.addFile(
|
|
73
|
+
'./package.json',
|
|
74
|
+
JSON.stringify({
|
|
75
|
+
dependencies: {
|
|
76
|
+
react: '^18.0.0',
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
await migrate(context);
|
|
82
|
+
|
|
83
|
+
const updatedPackageJson = JSON.parse(context.getFile('./package.json') || '{}');
|
|
84
|
+
expect(updatedPackageJson.dependencies.react).toBe('^18.3.1');
|
|
85
|
+
expect(updatedPackageJson.devDependencies?.['@types/react']).toBe('^18.3.1');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should not update React if version is already 18.3.1 or higher', async () => {
|
|
89
|
+
const context = new Context('/virtual');
|
|
90
|
+
const packageJson = {
|
|
91
|
+
dependencies: {
|
|
92
|
+
react: '^18.3.1',
|
|
93
|
+
'react-dom': '^18.3.1',
|
|
94
|
+
},
|
|
95
|
+
devDependencies: {
|
|
96
|
+
'@types/react': '^18.3.1',
|
|
97
|
+
'@types/react-dom': '^18.3.1',
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
context.addFile('./package.json', JSON.stringify(packageJson, null, 2));
|
|
101
|
+
|
|
102
|
+
await migrate(context);
|
|
103
|
+
|
|
104
|
+
// Since the versions are already 18.3.1, the migration should still run
|
|
105
|
+
// but the versions should remain 18.3.1
|
|
106
|
+
const updatedPackageJson = JSON.parse(context.getFile('./package.json') || '{}');
|
|
107
|
+
expect(updatedPackageJson.dependencies.react).toBe('^18.3.1');
|
|
108
|
+
expect(updatedPackageJson.dependencies['react-dom']).toBe('^18.3.1');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should handle version ranges correctly', async () => {
|
|
112
|
+
const context = new Context('/virtual');
|
|
113
|
+
context.addFile(
|
|
114
|
+
'./package.json',
|
|
115
|
+
JSON.stringify({
|
|
116
|
+
dependencies: {
|
|
117
|
+
react: '~18.1.0',
|
|
118
|
+
'react-dom': '18.2.0',
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
await migrate(context);
|
|
124
|
+
|
|
125
|
+
const updatedPackageJson = JSON.parse(context.getFile('./package.json') || '{}');
|
|
126
|
+
expect(updatedPackageJson.dependencies.react).toBe('^18.3.1');
|
|
127
|
+
expect(updatedPackageJson.dependencies['react-dom']).toBe('^18.3.1');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should be idempotent', async () => {
|
|
131
|
+
const context = new Context('/virtual');
|
|
132
|
+
context.addFile(
|
|
133
|
+
'./package.json',
|
|
134
|
+
JSON.stringify({
|
|
135
|
+
dependencies: {
|
|
136
|
+
react: '^18.2.0',
|
|
137
|
+
'react-dom': '^18.2.0',
|
|
138
|
+
},
|
|
139
|
+
devDependencies: {
|
|
140
|
+
'@types/react': '^18.2.0',
|
|
141
|
+
'@types/react-dom': '^18.2.0',
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
);
|
|
145
|
+
await expect(migrate).toBeIdempotent(context);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Context } from '../context.js';
|
|
2
|
+
import { addDependenciesToPackageJson, isVersionGreater } from '../utils.js';
|
|
3
|
+
|
|
4
|
+
export default function migrate(context: Context) {
|
|
5
|
+
if (context.doesFileExist('package.json')) {
|
|
6
|
+
const packageJson = JSON.parse(context.getFile('package.json') || '{}');
|
|
7
|
+
if (packageJson.dependencies?.react) {
|
|
8
|
+
if (isVersionGreater(packageJson.dependencies.react, '18.0.0', true)) {
|
|
9
|
+
addDependenciesToPackageJson(context, { react: '^18.3.1' }, { '@types/react': '^18.3.1' });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
if (packageJson.dependencies?.['react-dom']) {
|
|
13
|
+
if (isVersionGreater(packageJson.dependencies['react-dom'], '18.0.0', true)) {
|
|
14
|
+
addDependenciesToPackageJson(context, { 'react-dom': '^18.3.1' }, { '@types/react-dom': '^18.3.1' });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return context;
|
|
19
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import migrate from './example-migration.js';
|
|
2
|
-
import { createDefaultContext } from '
|
|
2
|
+
import { createDefaultContext } from '../test-utils.js';
|
|
3
3
|
|
|
4
4
|
describe('Migration - append profile to webpack', () => {
|
|
5
5
|
test('should update the package.json', async () => {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { dirSync } from 'tmp';
|
|
2
|
-
import { Context } from '
|
|
2
|
+
import { Context } from './context.js';
|
|
3
3
|
import {
|
|
4
4
|
addDependenciesToPackageJson,
|
|
5
5
|
removeDependenciesFromPackageJson,
|
|
6
6
|
flushChanges,
|
|
7
7
|
formatFiles,
|
|
8
|
+
printChanges,
|
|
8
9
|
readJsonFile,
|
|
9
10
|
isVersionGreater,
|
|
10
|
-
} from '
|
|
11
|
-
import { printChanges } from './utils.js';
|
|
11
|
+
} from './utils.js';
|
|
12
12
|
import { join } from 'node:path';
|
|
13
13
|
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
|
14
14
|
import { readFileSync } from 'node:fs';
|
|
15
|
-
import { output } from '
|
|
15
|
+
import { output } from '../utils/utils.console.js';
|
|
16
16
|
|
|
17
17
|
describe('utils', () => {
|
|
18
18
|
const tmpObj = dirSync({ unsafeCleanup: true });
|
|
@@ -1,30 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared utilities for codemods (migrations and additions).
|
|
3
|
-
* These functions work with the Context class to modify plugin codebases.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
1
|
import { dirname, join } from 'node:path';
|
|
7
2
|
import { createRequire } from 'node:module';
|
|
8
3
|
import { Context } from './context.js';
|
|
9
4
|
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { debug } from '../utils/utils.cli.js';
|
|
10
6
|
import chalk from 'chalk';
|
|
7
|
+
import { MigrationMeta } from './migrations.js';
|
|
11
8
|
import { output } from '../utils/utils.console.js';
|
|
12
9
|
import { getPackageManagerSilentInstallCmd, getPackageManagerWithFallback } from '../utils/utils.packageManager.js';
|
|
13
10
|
import { execSync } from 'node:child_process';
|
|
14
|
-
import { clean, coerce, gt } from 'semver';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Generic metadata type for printChanges
|
|
18
|
-
*/
|
|
19
|
-
type ChangeMetadata = {
|
|
20
|
-
description: string;
|
|
21
|
-
};
|
|
11
|
+
import { clean, coerce, gt, gte } from 'semver';
|
|
22
12
|
|
|
23
|
-
|
|
24
|
-
* Prints changes made to the context in a formatted way.
|
|
25
|
-
* Works with both migrations and additions.
|
|
26
|
-
*/
|
|
27
|
-
export function printChanges(context: Context, key: string, meta: ChangeMetadata) {
|
|
13
|
+
export function printChanges(context: Context, key: string, migration: MigrationMeta) {
|
|
28
14
|
const changes = context.listChanges();
|
|
29
15
|
const lines = [];
|
|
30
16
|
|
|
@@ -39,7 +25,7 @@ export function printChanges(context: Context, key: string, meta: ChangeMetadata
|
|
|
39
25
|
}
|
|
40
26
|
|
|
41
27
|
output.addHorizontalLine('gray');
|
|
42
|
-
output.logSingleLine(`${key} (${
|
|
28
|
+
output.logSingleLine(`${key} (${migration.description})`);
|
|
43
29
|
|
|
44
30
|
if (lines.length === 0) {
|
|
45
31
|
output.logSingleLine('No changes were made');
|
|
@@ -48,9 +34,6 @@ export function printChanges(context: Context, key: string, meta: ChangeMetadata
|
|
|
48
34
|
}
|
|
49
35
|
}
|
|
50
36
|
|
|
51
|
-
/**
|
|
52
|
-
* Writes all changes from the context to the filesystem.
|
|
53
|
-
*/
|
|
54
37
|
export function flushChanges(context: Context) {
|
|
55
38
|
const basePath = context.basePath;
|
|
56
39
|
const changes = context.listChanges();
|
|
@@ -68,8 +51,10 @@ export function flushChanges(context: Context) {
|
|
|
68
51
|
}
|
|
69
52
|
}
|
|
70
53
|
|
|
54
|
+
export const migrationsDebug = debug.extend('migrations');
|
|
55
|
+
|
|
71
56
|
/**
|
|
72
|
-
* Formats the files in the context using the version of prettier found in the local node_modules.
|
|
57
|
+
* Formats the files in the migration context using the version of prettier found in the local node_modules.
|
|
73
58
|
* If prettier isn't installed or the file is ignored or has no parser, it will not be formatted.
|
|
74
59
|
*
|
|
75
60
|
* @param context - The context to format.
|
|
@@ -119,12 +104,9 @@ export async function formatFiles(context: Context) {
|
|
|
119
104
|
}
|
|
120
105
|
|
|
121
106
|
// Cache the package.json contents to avoid re-installing dependencies if the package.json hasn't changed
|
|
122
|
-
// (This runs for each
|
|
107
|
+
// (This runs for each migration used in an update)
|
|
123
108
|
let packageJsonInstallCache: string;
|
|
124
109
|
|
|
125
|
-
/**
|
|
126
|
-
* Installs NPM dependencies if package.json has changed.
|
|
127
|
-
*/
|
|
128
110
|
export function installNPMDependencies(context: Context) {
|
|
129
111
|
const hasPackageJsonChanges = Object.entries(context.listChanges()).some(
|
|
130
112
|
([filePath, { changeType }]) => filePath === 'package.json' && changeType === 'update'
|
|
@@ -152,9 +134,6 @@ export function installNPMDependencies(context: Context) {
|
|
|
152
134
|
}
|
|
153
135
|
}
|
|
154
136
|
|
|
155
|
-
/**
|
|
156
|
-
* Reads and parses a JSON file from the context.
|
|
157
|
-
*/
|
|
158
137
|
export function readJsonFile<T extends object = any>(context: Context, path: string): T {
|
|
159
138
|
if (!context.doesFileExist(path)) {
|
|
160
139
|
throw new Error(`Cannot find ${path}`);
|
|
@@ -166,9 +145,6 @@ export function readJsonFile<T extends object = any>(context: Context, path: str
|
|
|
166
145
|
}
|
|
167
146
|
}
|
|
168
147
|
|
|
169
|
-
/**
|
|
170
|
-
* Adds or updates dependencies in package.json, preventing downgrades.
|
|
171
|
-
*/
|
|
172
148
|
export function addDependenciesToPackageJson(
|
|
173
149
|
context: Context,
|
|
174
150
|
dependencies: Record<string, string>,
|
|
@@ -184,10 +160,14 @@ export function addDependenciesToPackageJson(
|
|
|
184
160
|
if (currentDeps[dep]) {
|
|
185
161
|
if (isVersionGreater(newVersion, currentDeps[dep])) {
|
|
186
162
|
currentDeps[dep] = newVersion;
|
|
163
|
+
} else {
|
|
164
|
+
migrationsDebug('would downgrade dependency %s to %s', dep, newVersion);
|
|
187
165
|
}
|
|
188
166
|
} else if (currentDevDeps[dep]) {
|
|
189
167
|
if (isVersionGreater(newVersion, currentDevDeps[dep])) {
|
|
190
168
|
currentDevDeps[dep] = newVersion;
|
|
169
|
+
} else {
|
|
170
|
+
migrationsDebug('would downgrade devDependency %s to %s', dep, newVersion);
|
|
191
171
|
}
|
|
192
172
|
} else {
|
|
193
173
|
// Not present, add to dependencies
|
|
@@ -200,10 +180,14 @@ export function addDependenciesToPackageJson(
|
|
|
200
180
|
if (currentDeps[dep]) {
|
|
201
181
|
if (isVersionGreater(newVersion, currentDeps[dep])) {
|
|
202
182
|
currentDeps[dep] = newVersion;
|
|
183
|
+
} else {
|
|
184
|
+
migrationsDebug('would downgrade dependency %s to %s', dep, newVersion);
|
|
203
185
|
}
|
|
204
186
|
} else if (currentDevDeps[dep]) {
|
|
205
187
|
if (isVersionGreater(newVersion, currentDevDeps[dep])) {
|
|
206
188
|
currentDevDeps[dep] = newVersion;
|
|
189
|
+
} else {
|
|
190
|
+
migrationsDebug('would downgrade devDependency %s to %s', dep, newVersion);
|
|
207
191
|
}
|
|
208
192
|
} else {
|
|
209
193
|
// Not present, add to devDependencies
|
|
@@ -230,12 +214,11 @@ export function addDependenciesToPackageJson(
|
|
|
230
214
|
...(Object.keys(sortedDevDeps).length > 0 && { devDependencies: sortedDevDeps }),
|
|
231
215
|
};
|
|
232
216
|
|
|
217
|
+
migrationsDebug('updated package.json', updatedPackageJson);
|
|
218
|
+
|
|
233
219
|
context.updateFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2));
|
|
234
220
|
}
|
|
235
221
|
|
|
236
|
-
/**
|
|
237
|
-
* Removes dependencies from package.json.
|
|
238
|
-
*/
|
|
239
222
|
export function removeDependenciesFromPackageJson(
|
|
240
223
|
context: Context,
|
|
241
224
|
dependencies: string[],
|
|
@@ -249,6 +232,7 @@ export function removeDependenciesFromPackageJson(
|
|
|
249
232
|
for (const dep of dependencies) {
|
|
250
233
|
if (currentPackageJson.dependencies?.[dep]) {
|
|
251
234
|
delete currentPackageJson.dependencies[dep];
|
|
235
|
+
migrationsDebug('removed dependency %s', dep);
|
|
252
236
|
hasChanges = true;
|
|
253
237
|
}
|
|
254
238
|
}
|
|
@@ -256,6 +240,7 @@ export function removeDependenciesFromPackageJson(
|
|
|
256
240
|
for (const dep of devDependencies) {
|
|
257
241
|
if (currentPackageJson.devDependencies?.[dep]) {
|
|
258
242
|
delete currentPackageJson.devDependencies[dep];
|
|
243
|
+
migrationsDebug('removed devDependency %s', dep);
|
|
259
244
|
hasChanges = true;
|
|
260
245
|
}
|
|
261
246
|
}
|
|
@@ -264,6 +249,8 @@ export function removeDependenciesFromPackageJson(
|
|
|
264
249
|
return;
|
|
265
250
|
}
|
|
266
251
|
|
|
252
|
+
migrationsDebug('updated package.json', currentPackageJson);
|
|
253
|
+
|
|
267
254
|
context.updateFile(packageJsonPath, JSON.stringify(currentPackageJson, null, 2));
|
|
268
255
|
}
|
|
269
256
|
|
|
@@ -276,8 +263,13 @@ const DIST_TAGS = {
|
|
|
276
263
|
|
|
277
264
|
/**
|
|
278
265
|
* Compares two version strings to determine if the incoming version is greater
|
|
266
|
+
*
|
|
267
|
+
* @param incomingVersion - The incoming version to compare.
|
|
268
|
+
* @param existingVersion - The existing version to compare.
|
|
269
|
+
* @param orEqualTo - Whether to include the existing version in the comparison.
|
|
270
|
+
*
|
|
279
271
|
*/
|
|
280
|
-
export function isVersionGreater(incomingVersion: string, existingVersion: string)
|
|
272
|
+
export function isVersionGreater(incomingVersion: string, existingVersion: string, orEqualTo = false) {
|
|
281
273
|
const incomingIsDistTag = incomingVersion in DIST_TAGS;
|
|
282
274
|
const existingIsDistTag = existingVersion in DIST_TAGS;
|
|
283
275
|
|
|
@@ -301,6 +293,10 @@ export function isVersionGreater(incomingVersion: string, existingVersion: strin
|
|
|
301
293
|
return true;
|
|
302
294
|
}
|
|
303
295
|
|
|
296
|
+
if (orEqualTo) {
|
|
297
|
+
return gte(incomingSemver, existingSemver);
|
|
298
|
+
}
|
|
299
|
+
|
|
304
300
|
return gt(incomingSemver, existingSemver);
|
|
305
301
|
}
|
|
306
302
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { argv, commandName } from './utils.cli.js';
|
|
2
2
|
|
|
3
|
-
import type { AdditionFeatureName } from '../codemods/additions/additions.js';
|
|
4
3
|
import { CURRENT_APP_VERSION } from './utils.version.js';
|
|
5
4
|
import { DEFAULT_FEATURE_FLAGS } from '../constants.js';
|
|
6
5
|
import fs from 'node:fs';
|
|
@@ -10,27 +9,16 @@ import path from 'node:path';
|
|
|
10
9
|
import { writeFile } from 'node:fs/promises';
|
|
11
10
|
import { EOL } from 'node:os';
|
|
12
11
|
|
|
13
|
-
type
|
|
12
|
+
export type FeatureFlags = {
|
|
14
13
|
bundleGrafanaUI?: boolean;
|
|
15
14
|
|
|
16
15
|
// If set to true, the plugin will be scaffolded with React Router v6. Defaults to true.
|
|
17
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.)
|
|
18
17
|
useReactRouterV6?: boolean;
|
|
19
|
-
usePlaywright?: boolean;
|
|
20
18
|
useExperimentalRspack?: boolean;
|
|
21
19
|
useExperimentalUpdates?: boolean;
|
|
22
20
|
};
|
|
23
21
|
|
|
24
|
-
type AdditionFeatureFlags = {
|
|
25
|
-
[K in AdditionFeatureName]?: boolean;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export type FeatureFlags = CoreFeatureFlags & AdditionFeatureFlags;
|
|
29
|
-
|
|
30
|
-
export function isFeatureEnabled(features: FeatureFlags, featureName: AdditionFeatureName): boolean {
|
|
31
|
-
return features[featureName] === true;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
22
|
export type CreatePluginConfig = UserConfig & {
|
|
35
23
|
version: string;
|
|
36
24
|
};
|
|
@@ -144,18 +132,3 @@ export async function setRootConfig(configOverride: Partial<CreatePluginConfig>
|
|
|
144
132
|
|
|
145
133
|
return updatedConfig;
|
|
146
134
|
}
|
|
147
|
-
|
|
148
|
-
export async function setFeatureFlag(featureName: string, enabled = true): Promise<void> {
|
|
149
|
-
const userConfig = getUserConfig() || { features: {} };
|
|
150
|
-
const userConfigPath = path.resolve(process.cwd(), '.cprc.json');
|
|
151
|
-
|
|
152
|
-
const updatedConfig = {
|
|
153
|
-
...userConfig,
|
|
154
|
-
features: {
|
|
155
|
-
...userConfig.features,
|
|
156
|
-
[featureName]: enabled,
|
|
157
|
-
},
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
await writeFile(userConfigPath, JSON.stringify(updatedConfig, null, 2) + EOL);
|
|
161
|
-
}
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"@testing-library/jest-dom": "6.1.4",
|
|
30
30
|
"@testing-library/react": "14.0.0",
|
|
31
31
|
"@types/jest": "^29.5.0",
|
|
32
|
-
"@types/node": "^20.8.7",
|
|
32
|
+
"@types/node": "^20.8.7",
|
|
33
|
+
"@types/react": "^18.3.0",
|
|
34
|
+
"@types/react-dom": "^18.3.0",{{#if isAppType}}{{#unless useReactRouterV6}}
|
|
33
35
|
"@types/react-router-dom": "^{{ reactRouterVersion }}",{{/unless}}{{/if}}
|
|
34
36
|
"@types/testing-library__jest-dom": "5.14.8",
|
|
35
37
|
"@typescript-eslint/eslint-plugin": "^8.3.0",
|
|
@@ -77,8 +79,8 @@
|
|
|
77
79
|
"@grafana/ui": "^12.2.1",
|
|
78
80
|
"@grafana/schema": "^12.2.1",{{#if_eq pluginType "scenesapp" }}
|
|
79
81
|
"@grafana/scenes": "{{ scenesVersion }}",{{/if_eq}}
|
|
80
|
-
"react": "18.
|
|
81
|
-
"react-dom": "18.
|
|
82
|
+
"react": "^18.3.0",
|
|
83
|
+
"react-dom": "^18.3.0"{{#if isAppType}},
|
|
82
84
|
"react-router-dom": "^{{ reactRouterVersion }}",
|
|
83
85
|
"rxjs": "7.8.2"{{/if}}
|
|
84
86
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
{{!-- /* 🚨 The `${{ }}` Github workflow expressions need to be escaped so they are not being interpreted by Handlebars. (this comment is going to be removed after scaffolding) 🚨 */ --}}
|
|
1
2
|
name: Create Plugin Update
|
|
2
3
|
|
|
3
4
|
on:
|
|
@@ -5,22 +6,16 @@ on:
|
|
|
5
6
|
schedule:
|
|
6
7
|
- cron: '0 0 1 * *' # run once a month on the 1st day
|
|
7
8
|
|
|
8
|
-
# To use
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# `
|
|
12
|
-
|
|
13
|
-
permissions:
|
|
14
|
-
contents: write
|
|
15
|
-
pull-requests: write
|
|
9
|
+
# To use this workflow please create a fine-grained personal access token for your repository with:
|
|
10
|
+
# `contents: read and write`
|
|
11
|
+
# `pull requests: read and write`
|
|
12
|
+
# `workflows: read and write`
|
|
16
13
|
|
|
17
14
|
jobs:
|
|
18
15
|
release:
|
|
19
16
|
runs-on: ubuntu-latest
|
|
20
17
|
steps:
|
|
21
18
|
- uses: grafana/plugin-actions/create-plugin-update@create-plugin-update/v1.1.0
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# Make sure to save the token in your repository secrets
|
|
26
|
-
# token: ${{ secrets.GH_PAT_TOKEN }}
|
|
19
|
+
with:
|
|
20
|
+
# Make sure to save the token in your repository secrets as `GH_PAT_TOKEN`
|
|
21
|
+
token: $\{{ secrets.GH_PAT_TOKEN }}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const additions = {
|
|
2
|
-
i18n: {
|
|
3
|
-
name: "i18n",
|
|
4
|
-
description: "Add internationalization (i18n) support to your plugin",
|
|
5
|
-
scriptPath: "./scripts/add-i18n.js",
|
|
6
|
-
featureName: "i18nEnabled"
|
|
7
|
-
}
|
|
8
|
-
};
|
|
9
|
-
var defaultAdditions = { additions };
|
|
10
|
-
|
|
11
|
-
export { defaultAdditions as default };
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { additionsDebug, printChanges } from './utils.js';
|
|
2
|
-
import defaultAdditions from './additions.js';
|
|
3
|
-
import { formatFiles, flushChanges, installNPMDependencies } from '../utils.js';
|
|
4
|
-
import { getConfig, isFeatureEnabled, setFeatureFlag } from '../../utils/utils.config.js';
|
|
5
|
-
import { Context } from '../context.js';
|
|
6
|
-
import { output } from '../../utils/utils.console.js';
|
|
7
|
-
|
|
8
|
-
function getAvailableAdditions(additions = defaultAdditions.additions) {
|
|
9
|
-
return additions;
|
|
10
|
-
}
|
|
11
|
-
function getAdditionByName(name, additions = defaultAdditions.additions) {
|
|
12
|
-
return additions[name];
|
|
13
|
-
}
|
|
14
|
-
async function loadAdditionModule(addition) {
|
|
15
|
-
try {
|
|
16
|
-
const module = await import(addition.scriptPath);
|
|
17
|
-
return module;
|
|
18
|
-
} catch (error) {
|
|
19
|
-
additionsDebug('Failed to load addition module for "%s" from %s: %O', addition.name, addition.scriptPath, error);
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
async function getAdditionFlags(addition) {
|
|
24
|
-
const module = await loadAdditionModule(addition);
|
|
25
|
-
return module?.flags || [];
|
|
26
|
-
}
|
|
27
|
-
async function parseAdditionFlags(addition, argv) {
|
|
28
|
-
const module = await loadAdditionModule(addition);
|
|
29
|
-
if (module?.parseFlags) {
|
|
30
|
-
return module.parseFlags(argv);
|
|
31
|
-
}
|
|
32
|
-
return {};
|
|
33
|
-
}
|
|
34
|
-
async function validateAdditionOptions(addition, options) {
|
|
35
|
-
const flags = await getAdditionFlags(addition);
|
|
36
|
-
if (!flags || flags.length === 0) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const missingFlags = [];
|
|
40
|
-
for (const flag of flags) {
|
|
41
|
-
if (flag.required) {
|
|
42
|
-
const value = options[flag.name];
|
|
43
|
-
if (value === void 0 || value === null || Array.isArray(value) && value.length === 0) {
|
|
44
|
-
missingFlags.push(flag.name);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (missingFlags.length > 0) {
|
|
49
|
-
const flagDocs = flags.filter((f) => missingFlags.includes(f.name)).map((f) => ` --${f.name}: ${f.description}`);
|
|
50
|
-
throw new Error(
|
|
51
|
-
`Missing required flag${missingFlags.length > 1 ? "s" : ""}:
|
|
52
|
-
|
|
53
|
-
` + flagDocs.join("\n") + `
|
|
54
|
-
|
|
55
|
-
Example: npx @grafana/create-plugin add ${addition.name} --${missingFlags[0]}=value`
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
async function runAdditionByName(additionName, argv) {
|
|
60
|
-
const addition = getAdditionByName(additionName);
|
|
61
|
-
if (!addition) {
|
|
62
|
-
const availableAdditions = getAvailableAdditions();
|
|
63
|
-
const additionsList = Object.keys(availableAdditions);
|
|
64
|
-
throw new Error(`Unknown addition: ${additionName}
|
|
65
|
-
|
|
66
|
-
Available additions: ${additionsList.join(", ")}`);
|
|
67
|
-
}
|
|
68
|
-
const options = await parseAdditionFlags(addition, argv);
|
|
69
|
-
await validateAdditionOptions(addition, options);
|
|
70
|
-
await runAddition(addition, options);
|
|
71
|
-
}
|
|
72
|
-
async function runAddition(addition, additionOptions = {}) {
|
|
73
|
-
const basePath = process.cwd();
|
|
74
|
-
const config = getConfig();
|
|
75
|
-
if (isFeatureEnabled(config.features, addition.featureName)) {
|
|
76
|
-
output.log({
|
|
77
|
-
title: `Addition '${addition.name}' is already enabled`,
|
|
78
|
-
body: [`The feature flag '${addition.featureName}' is already set to true in .cprc.json.`, "No changes needed."]
|
|
79
|
-
});
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
output.log({
|
|
83
|
-
title: `Running addition: ${addition.name}`,
|
|
84
|
-
body: [addition.description]
|
|
85
|
-
});
|
|
86
|
-
try {
|
|
87
|
-
const context = new Context(basePath);
|
|
88
|
-
const updatedContext = await executeAddition(addition, context, additionOptions);
|
|
89
|
-
additionsDebug(`context for "${addition.name} (${addition.scriptPath})":`);
|
|
90
|
-
additionsDebug("%O", updatedContext.listChanges());
|
|
91
|
-
await formatFiles(updatedContext);
|
|
92
|
-
flushChanges(updatedContext);
|
|
93
|
-
printChanges(updatedContext, addition.name, addition);
|
|
94
|
-
installNPMDependencies(updatedContext);
|
|
95
|
-
await setFeatureFlag(addition.featureName, true);
|
|
96
|
-
additionsDebug(`Set feature flag '${addition.featureName}' to true in .cprc.json`);
|
|
97
|
-
output.success({
|
|
98
|
-
title: `Successfully added ${addition.name} to your plugin.`
|
|
99
|
-
});
|
|
100
|
-
} catch (error) {
|
|
101
|
-
if (error instanceof Error) {
|
|
102
|
-
throw new Error(`Error running addition "${addition.name} (${addition.scriptPath})": ${error.message}`);
|
|
103
|
-
}
|
|
104
|
-
throw error;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
async function executeAddition(addition, context, options = {}) {
|
|
108
|
-
const module = await loadAdditionModule(addition);
|
|
109
|
-
if (!module) {
|
|
110
|
-
throw new Error(`Failed to load addition module for ${addition.name}`);
|
|
111
|
-
}
|
|
112
|
-
return module.default(context, options);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export { executeAddition, getAdditionByName, getAdditionFlags, getAvailableAdditions, parseAdditionFlags, runAddition, runAdditionByName };
|