@grafana/create-plugin 6.2.0-canary.2233.19097561440.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/CONTRIBUTING.md +3 -0
  3. package/dist/bin/run.js +1 -3
  4. package/dist/commands/update.command.js +1 -1
  5. package/dist/{codemods → migrations}/context.js +2 -3
  6. package/dist/{codemods/migrations → migrations}/manager.js +7 -8
  7. package/dist/{codemods/migrations → migrations}/migrations.js +6 -3
  8. package/dist/{codemods/migrations → migrations}/scripts/003-update-eslint-deprecation-rule.js +1 -1
  9. package/dist/{codemods/migrations → migrations}/scripts/004-eslint9-flat-config.js +1 -2
  10. package/dist/migrations/scripts/005-react-18-3.js +20 -0
  11. package/dist/{codemods → migrations}/utils.js +22 -5
  12. package/dist/utils/utils.config.js +1 -16
  13. package/package.json +2 -2
  14. package/src/bin/run.ts +1 -2
  15. package/src/commands/index.ts +0 -1
  16. package/src/commands/update.command.ts +1 -1
  17. package/src/{codemods → migrations}/context.test.ts +10 -10
  18. package/src/{codemods → migrations}/context.ts +2 -4
  19. package/src/{codemods/migrations → migrations}/manager.test.ts +10 -15
  20. package/src/{codemods/migrations → migrations}/manager.ts +9 -10
  21. package/src/{codemods/migrations → migrations}/migrations.ts +8 -3
  22. package/src/{codemods/migrations → migrations}/scripts/001-update-grafana-compose-extend.test.ts +1 -1
  23. package/src/{codemods/migrations → migrations}/scripts/001-update-grafana-compose-extend.ts +1 -1
  24. package/src/{codemods/migrations → migrations}/scripts/002-update-is-compatible-workflow.test.ts +1 -1
  25. package/src/{codemods/migrations → migrations}/scripts/002-update-is-compatible-workflow.ts +1 -1
  26. package/src/{codemods/migrations → migrations}/scripts/003-update-eslint-deprecation-rule.test.ts +1 -1
  27. package/src/{codemods/migrations → migrations}/scripts/003-update-eslint-deprecation-rule.ts +2 -2
  28. package/src/{codemods/migrations → migrations}/scripts/004-eslint9-flat-config.test.ts +1 -1
  29. package/src/{codemods/migrations → migrations}/scripts/004-eslint9-flat-config.ts +2 -3
  30. package/src/migrations/scripts/005-react-18-3.test.ts +147 -0
  31. package/src/migrations/scripts/005-react-18-3.ts +19 -0
  32. package/src/{codemods/migrations → migrations}/scripts/example-migration.test.ts +1 -1
  33. package/src/{codemods/migrations → migrations}/scripts/example-migration.ts +1 -1
  34. package/src/{codemods/migrations → migrations}/utils.test.ts +4 -4
  35. package/src/{codemods → migrations}/utils.ts +33 -37
  36. package/src/utils/utils.config.ts +1 -28
  37. package/templates/common/_package.json +5 -3
  38. package/templates/github/workflows/cp-update.yml +8 -13
  39. package/dist/codemods/additions/additions.js +0 -11
  40. package/dist/codemods/additions/manager.js +0 -115
  41. package/dist/codemods/additions/scripts/add-i18n.js +0 -445
  42. package/dist/codemods/additions/utils.js +0 -10
  43. package/dist/codemods/migrations/utils.js +0 -10
  44. package/dist/commands/add.command.js +0 -86
  45. package/src/codemods/additions/additions.ts +0 -23
  46. package/src/codemods/additions/manager.ts +0 -145
  47. package/src/codemods/additions/scripts/add-i18n.test.ts +0 -347
  48. package/src/codemods/additions/scripts/add-i18n.ts +0 -584
  49. package/src/codemods/additions/utils.ts +0 -12
  50. package/src/codemods/migrations/utils.ts +0 -12
  51. package/src/codemods/types.ts +0 -21
  52. package/src/commands/add.command.ts +0 -97
  53. /package/dist/{codemods/migrations → migrations}/scripts/001-update-grafana-compose-extend.js +0 -0
  54. /package/dist/{codemods/migrations → migrations}/scripts/002-update-is-compatible-workflow.js +0 -0
  55. /package/dist/{codemods/migrations → migrations}/scripts/example-migration.js +0 -0
  56. /package/src/{codemods/migrations → migrations}/fixtures/foo/bar.ts +0 -0
  57. /package/src/{codemods/migrations → migrations}/fixtures/foo/baz.ts +0 -0
  58. /package/src/{codemods/migrations → migrations}/fixtures/migrations.ts +0 -0
  59. /package/src/{codemods/migrations → migrations}/migrations.test.ts +0 -0
  60. /package/src/{codemods → migrations}/test-utils.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ # v6.1.8 (Fri Nov 07 2025)
2
+
3
+ ### Release Notes
4
+
5
+ #### chore(deps): update grafana patch dependencies ([#2217](https://github.com/grafana/plugin-tools/pull/2217))
6
+
7
+ <details>
8
+ <summary>grafana/grafana (@&#8203;grafana/data)</summary>
9
+
10
+ ---
11
+
12
+ #### 🐛 Bug Fix
13
+
14
+ - Create plugin: fix permissions issue in cp-update workflow [#2281](https://github.com/grafana/plugin-tools/pull/2281) ([@jackw](https://github.com/jackw))
15
+ - chore(deps): update grafana patch dependencies [#2217](https://github.com/grafana/plugin-tools/pull/2217) ([@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot]))
16
+
17
+ #### Authors: 2
18
+
19
+ - [@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot])
20
+ - Jack Westbrook ([@jackw](https://github.com/jackw))
21
+
22
+ ---
23
+
1
24
  # v6.1.7 (Mon Nov 03 2025)
2
25
 
3
26
  :tada: This release contains work from a new contributor! :tada:
package/CONTRIBUTING.md CHANGED
@@ -222,6 +222,9 @@ describe('Migration - append profile to webpack', () => {
222
222
  });
223
223
  ```
224
224
 
225
+ > [!TIP]
226
+ > A lot of the code used by migrations has debug messaging. You can output this in tests to help debugging by using `DEBUG="create-plugin:migrations" npm run test -w @grafana/create-plugin`
227
+
225
228
  #### How to test a migration locally
226
229
 
227
230
  To test a migration locally you'll need a plugin to test on.
package/dist/bin/run.js CHANGED
@@ -4,7 +4,6 @@ import { update } from '../commands/update.command.js';
4
4
  import { migrate } from '../commands/migrate.command.js';
5
5
  import { version } from '../commands/version.command.js';
6
6
  import { provisioning } from '../commands/provisioning.command.js';
7
- import { add } from '../commands/add.command.js';
8
7
  import { isUnsupportedPlatform } from '../utils/utils.os.js';
9
8
  import { argv, commandName } from '../utils/utils.cli.js';
10
9
  import { output } from '../utils/utils.console.js';
@@ -22,8 +21,7 @@ const commands = {
22
21
  generate,
23
22
  update,
24
23
  version,
25
- provisioning,
26
- add
24
+ provisioning
27
25
  };
28
26
  const command = commands[commandName] || "generate";
29
27
  command(argv);
@@ -1,4 +1,4 @@
1
- import { getMigrationsToRun, runMigrations } from '../codemods/migrations/manager.js';
1
+ import { getMigrationsToRun, runMigrations } from '../migrations/manager.js';
2
2
  import { getPackageManagerWithFallback, getPackageManagerExecCmd, getPackageManagerSilentInstallCmd } from '../utils/utils.packageManager.js';
3
3
  import { lt, gte } from 'semver';
4
4
  import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
@@ -1,11 +1,10 @@
1
1
  import { accessSync, constants, readFileSync, readdirSync } from 'node:fs';
2
2
  import { join, dirname, normalize, relative } from 'node:path';
3
- import { debug } from '../utils/utils.cli.js';
3
+ import { migrationsDebug } from './utils.js';
4
4
 
5
5
  var __defProp = Object.defineProperty;
6
6
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
7
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
- const codemodsDebug = debug.extend("codemods");
9
8
  class Context {
10
9
  constructor(basePath) {
11
10
  __publicField(this, "files", {});
@@ -42,7 +41,7 @@ class Context {
42
41
  if (originalContent !== content) {
43
42
  this.files[path] = { content, changeType: "update" };
44
43
  } else {
45
- codemodsDebug(`Context.updateFile() - no updates for ${filePath}`);
44
+ migrationsDebug(`Context.updateFile() - no updates for ${filePath}`);
46
45
  }
47
46
  }
48
47
  doesFileExist(filePath) {
@@ -1,12 +1,11 @@
1
- import defaultMigrations from './migrations.js';
2
- import { formatFiles, flushChanges, installNPMDependencies } from '../utils.js';
3
1
  import { gte, satisfies } from 'semver';
4
- import { migrationsDebug, printChanges } from './utils.js';
5
- import { CURRENT_APP_VERSION } from '../../utils/utils.version.js';
6
- import { Context } from '../context.js';
7
- import { gitCommitNoVerify } from '../../utils/utils.git.js';
8
- import { output } from '../../utils/utils.console.js';
9
- import { setRootConfig } from '../../utils/utils.config.js';
2
+ import { Context } from './context.js';
3
+ import defaultMigrations from './migrations.js';
4
+ import { migrationsDebug, formatFiles, flushChanges, printChanges, installNPMDependencies } from './utils.js';
5
+ import { gitCommitNoVerify } from '../utils/utils.git.js';
6
+ import { setRootConfig } from '../utils/utils.config.js';
7
+ import { output } from '../utils/utils.console.js';
8
+ import { CURRENT_APP_VERSION } from '../utils/utils.version.js';
10
9
 
11
10
  function getMigrationsToRun(fromVersion, toVersion, migrations = defaultMigrations.migrations) {
12
11
  const semverRange = `${fromVersion} - ${toVersion}`;
@@ -1,4 +1,4 @@
1
- import { LEGACY_UPDATE_CUTOFF_VERSION } from '../../constants.js';
1
+ import { LEGACY_UPDATE_CUTOFF_VERSION } from '../constants.js';
2
2
 
3
3
  var defaultMigrations = {
4
4
  migrations: {
@@ -21,9 +21,12 @@ var defaultMigrations = {
21
21
  version: LEGACY_UPDATE_CUTOFF_VERSION,
22
22
  description: "Migrate eslint config to flat config format and update devDependencies to latest versions.",
23
23
  migrationScript: "./scripts/004-eslint9-flat-config.js"
24
+ },
25
+ "005-react-18-3": {
26
+ version: "6.1.7-beta.1",
27
+ description: "Update React 18.0.0 to 18.3.1.",
28
+ migrationScript: "./scripts/005-react-18-3.js"
24
29
  }
25
- // Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It is only used above to force migrations to run
26
- // for those written before the switch to updates as migrations.
27
30
  }
28
31
  };
29
32
 
@@ -1,4 +1,4 @@
1
- import { addDependenciesToPackageJson, removeDependenciesFromPackageJson } from '../../utils.js';
1
+ import { addDependenciesToPackageJson, removeDependenciesFromPackageJson } from '../utils.js';
2
2
 
3
3
  function migrate(context) {
4
4
  if (context.doesFileExist(".config/.eslintrc") && context.doesFileExist("package.json")) {
@@ -4,8 +4,7 @@ import { parse } from 'jsonc-parser';
4
4
  import minimist from 'minimist';
5
5
  import { resolve, dirname, relative } from 'node:path';
6
6
  import * as recast from 'recast';
7
- import { addDependenciesToPackageJson } from '../../utils.js';
8
- import { migrationsDebug } from '../utils.js';
7
+ import { addDependenciesToPackageJson, migrationsDebug } from '../utils.js';
9
8
 
10
9
  const { builders } = recast.types;
11
10
  const legacyKeysToCopy = ["rules", "settings"];
@@ -0,0 +1,20 @@
1
+ import { isVersionGreater, addDependenciesToPackageJson } from '../utils.js';
2
+
3
+ function migrate(context) {
4
+ if (context.doesFileExist("package.json")) {
5
+ const packageJson = JSON.parse(context.getFile("package.json") || "{}");
6
+ if (packageJson.dependencies?.react) {
7
+ if (isVersionGreater(packageJson.dependencies.react, "18.0.0", true)) {
8
+ addDependenciesToPackageJson(context, { react: "^18.3.1" }, { "@types/react": "^18.3.1" });
9
+ }
10
+ }
11
+ if (packageJson.dependencies?.["react-dom"]) {
12
+ if (isVersionGreater(packageJson.dependencies["react-dom"], "18.0.0", true)) {
13
+ addDependenciesToPackageJson(context, { "react-dom": "^18.3.1" }, { "@types/react-dom": "^18.3.1" });
14
+ }
15
+ }
16
+ }
17
+ return context;
18
+ }
19
+
20
+ export { migrate as default };
@@ -1,13 +1,14 @@
1
1
  import { join, dirname } from 'node:path';
2
2
  import { createRequire } from 'node:module';
3
3
  import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
4
+ import { debug } from '../utils/utils.cli.js';
4
5
  import chalk from 'chalk';
5
6
  import { output } from '../utils/utils.console.js';
6
7
  import { getPackageManagerWithFallback, getPackageManagerSilentInstallCmd } from '../utils/utils.packageManager.js';
7
8
  import { execSync } from 'node:child_process';
8
- import { gt, clean, coerce } from 'semver';
9
+ import { gte, gt, clean, coerce } from 'semver';
9
10
 
10
- function printChanges(context, key, meta) {
11
+ function printChanges(context, key, migration) {
11
12
  const changes = context.listChanges();
12
13
  const lines = [];
13
14
  for (const [filePath, { changeType }] of Object.entries(changes)) {
@@ -20,7 +21,7 @@ function printChanges(context, key, meta) {
20
21
  }
21
22
  }
22
23
  output.addHorizontalLine("gray");
23
- output.logSingleLine(`${key} (${meta.description})`);
24
+ output.logSingleLine(`${key} (${migration.description})`);
24
25
  if (lines.length === 0) {
25
26
  output.logSingleLine("No changes were made");
26
27
  } else {
@@ -42,6 +43,7 @@ function flushChanges(context) {
42
43
  }
43
44
  }
44
45
  }
46
+ const migrationsDebug = debug.extend("migrations");
45
47
  async function formatFiles(context) {
46
48
  let prettier;
47
49
  const require = createRequire(import.meta.url);
@@ -118,10 +120,14 @@ function addDependenciesToPackageJson(context, dependencies, devDependencies = {
118
120
  if (currentDeps[dep]) {
119
121
  if (isVersionGreater(newVersion, currentDeps[dep])) {
120
122
  currentDeps[dep] = newVersion;
123
+ } else {
124
+ migrationsDebug("would downgrade dependency %s to %s", dep, newVersion);
121
125
  }
122
126
  } else if (currentDevDeps[dep]) {
123
127
  if (isVersionGreater(newVersion, currentDevDeps[dep])) {
124
128
  currentDevDeps[dep] = newVersion;
129
+ } else {
130
+ migrationsDebug("would downgrade devDependency %s to %s", dep, newVersion);
125
131
  }
126
132
  } else {
127
133
  currentDeps[dep] = newVersion;
@@ -131,10 +137,14 @@ function addDependenciesToPackageJson(context, dependencies, devDependencies = {
131
137
  if (currentDeps[dep]) {
132
138
  if (isVersionGreater(newVersion, currentDeps[dep])) {
133
139
  currentDeps[dep] = newVersion;
140
+ } else {
141
+ migrationsDebug("would downgrade dependency %s to %s", dep, newVersion);
134
142
  }
135
143
  } else if (currentDevDeps[dep]) {
136
144
  if (isVersionGreater(newVersion, currentDevDeps[dep])) {
137
145
  currentDevDeps[dep] = newVersion;
146
+ } else {
147
+ migrationsDebug("would downgrade devDependency %s to %s", dep, newVersion);
138
148
  }
139
149
  } else {
140
150
  currentDevDeps[dep] = newVersion;
@@ -151,6 +161,7 @@ function addDependenciesToPackageJson(context, dependencies, devDependencies = {
151
161
  ...Object.keys(sortedDeps).length > 0 && { dependencies: sortedDeps },
152
162
  ...Object.keys(sortedDevDeps).length > 0 && { devDependencies: sortedDevDeps }
153
163
  };
164
+ migrationsDebug("updated package.json", updatedPackageJson);
154
165
  context.updateFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2));
155
166
  }
156
167
  function removeDependenciesFromPackageJson(context, dependencies, devDependencies = [], packageJsonPath = "package.json") {
@@ -159,18 +170,21 @@ function removeDependenciesFromPackageJson(context, dependencies, devDependencie
159
170
  for (const dep of dependencies) {
160
171
  if (currentPackageJson.dependencies?.[dep]) {
161
172
  delete currentPackageJson.dependencies[dep];
173
+ migrationsDebug("removed dependency %s", dep);
162
174
  hasChanges = true;
163
175
  }
164
176
  }
165
177
  for (const dep of devDependencies) {
166
178
  if (currentPackageJson.devDependencies?.[dep]) {
167
179
  delete currentPackageJson.devDependencies[dep];
180
+ migrationsDebug("removed devDependency %s", dep);
168
181
  hasChanges = true;
169
182
  }
170
183
  }
171
184
  if (!hasChanges) {
172
185
  return;
173
186
  }
187
+ migrationsDebug("updated package.json", currentPackageJson);
174
188
  context.updateFile(packageJsonPath, JSON.stringify(currentPackageJson, null, 2));
175
189
  }
176
190
  const DIST_TAGS = {
@@ -178,7 +192,7 @@ const DIST_TAGS = {
178
192
  next: 1,
179
193
  latest: 0
180
194
  };
181
- function isVersionGreater(incomingVersion, existingVersion) {
195
+ function isVersionGreater(incomingVersion, existingVersion, orEqualTo = false) {
182
196
  const incomingIsDistTag = incomingVersion in DIST_TAGS;
183
197
  const existingIsDistTag = existingVersion in DIST_TAGS;
184
198
  if (incomingIsDistTag && existingIsDistTag) {
@@ -192,6 +206,9 @@ function isVersionGreater(incomingVersion, existingVersion) {
192
206
  if (!incomingSemver || !existingSemver) {
193
207
  return true;
194
208
  }
209
+ if (orEqualTo) {
210
+ return gte(incomingSemver, existingSemver);
211
+ }
195
212
  return gt(incomingSemver, existingSemver);
196
213
  }
197
214
  function cleanSemver(version) {
@@ -201,4 +218,4 @@ function sortObjectByKeys(obj) {
201
218
  return Object.keys(obj).sort().reduce((acc, key) => ({ ...acc, [key]: obj[key] }), {});
202
219
  }
203
220
 
204
- export { addDependenciesToPackageJson, flushChanges, formatFiles, installNPMDependencies, isVersionGreater, printChanges, readJsonFile, removeDependenciesFromPackageJson };
221
+ export { addDependenciesToPackageJson, flushChanges, formatFiles, installNPMDependencies, isVersionGreater, migrationsDebug, printChanges, readJsonFile, removeDependenciesFromPackageJson };
@@ -8,9 +8,6 @@ import path from 'node:path';
8
8
  import { writeFile } from 'node:fs/promises';
9
9
  import { EOL } from 'node:os';
10
10
 
11
- function isFeatureEnabled(features, featureName) {
12
- return features[featureName] === true;
13
- }
14
11
  let hasShownConfigWarnings = false;
15
12
  function getConfig(workDir = process.cwd()) {
16
13
  const rootConfig = getRootConfig(workDir);
@@ -95,17 +92,5 @@ async function setRootConfig(configOverride = {}) {
95
92
  await writeFile(rootConfigPath, JSON.stringify(updatedConfig, null, 2) + EOL);
96
93
  return updatedConfig;
97
94
  }
98
- async function setFeatureFlag(featureName, enabled = true) {
99
- const userConfig = getUserConfig() || { features: {} };
100
- const userConfigPath = path.resolve(process.cwd(), ".cprc.json");
101
- const updatedConfig = {
102
- ...userConfig,
103
- features: {
104
- ...userConfig.features,
105
- [featureName]: enabled
106
- }
107
- };
108
- await writeFile(userConfigPath, JSON.stringify(updatedConfig, null, 2) + EOL);
109
- }
110
95
 
111
- export { getConfig, isFeatureEnabled, setFeatureFlag, setRootConfig };
96
+ export { getConfig, setRootConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafana/create-plugin",
3
- "version": "6.2.0-canary.2233.19097561440.0",
3
+ "version": "6.2.0-canary.2283.19173715977.0",
4
4
  "repository": {
5
5
  "directory": "packages/create-plugin",
6
6
  "url": "https://github.com/grafana/plugin-tools"
@@ -59,5 +59,5 @@
59
59
  "engines": {
60
60
  "node": ">=20"
61
61
  },
62
- "gitHead": "51cedf8d3738d2ca2401063cd1cae3f06140ce63"
62
+ "gitHead": "d05bd68a9727b078ce0c15029a1dbc86644714d3"
63
63
  }
package/src/bin/run.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import minimist from 'minimist';
4
- import { add, generate, update, migrate, version, provisioning } from '../commands/index.js';
4
+ import { generate, update, migrate, version, provisioning } from '../commands/index.js';
5
5
  import { isUnsupportedPlatform } from '../utils/utils.os.js';
6
6
  import { argv, commandName } from '../utils/utils.cli.js';
7
7
  import { output } from '../utils/utils.console.js';
@@ -23,7 +23,6 @@ const commands: Record<string, (argv: minimist.ParsedArgs) => void> = {
23
23
  update,
24
24
  version,
25
25
  provisioning,
26
- add,
27
26
  };
28
27
  const command = commands[commandName] || 'generate';
29
28
 
@@ -3,4 +3,3 @@ export * from './update.command.js';
3
3
  export * from './migrate.command.js';
4
4
  export * from './version.command.js';
5
5
  export * from './provisioning.command.js';
6
- export * from './add.command.js';
@@ -1,4 +1,4 @@
1
- import { getMigrationsToRun, runMigrations } from '../codemods/migrations/manager.js';
1
+ import { getMigrationsToRun, runMigrations } from '../migrations/manager.js';
2
2
  import {
3
3
  getPackageManagerExecCmd,
4
4
  getPackageManagerSilentInstallCmd,
@@ -3,7 +3,7 @@ import { Context } from './context.js';
3
3
  describe('Context', () => {
4
4
  describe('getFile', () => {
5
5
  it('should read a file from the file system', () => {
6
- const context = new Context(`${__dirname}/migrations/fixtures`);
6
+ const context = new Context(`${__dirname}/fixtures`);
7
7
  const content = context.getFile('foo/bar.ts');
8
8
  expect(content).toEqual("console.log('foo/bar.ts');\n");
9
9
  });
@@ -16,14 +16,14 @@ describe('Context', () => {
16
16
  });
17
17
 
18
18
  it('should get a file that was updated in the current context', () => {
19
- const context = new Context(`${__dirname}/migrations/fixtures`);
19
+ const context = new Context(`${__dirname}/fixtures`);
20
20
  context.updateFile('foo/bar.ts', 'content');
21
21
  const content = context.getFile('foo/bar.ts');
22
22
  expect(content).toEqual('content');
23
23
  });
24
24
 
25
25
  it('should not return a file that was marked for deletion', () => {
26
- const context = new Context(`${__dirname}/migrations/fixtures`);
26
+ const context = new Context(`${__dirname}/fixtures`);
27
27
  context.deleteFile('foo/bar.ts');
28
28
  const content = context.getFile('foo/bar.ts');
29
29
  expect(content).toEqual(undefined);
@@ -77,7 +77,7 @@ describe('Context', () => {
77
77
 
78
78
  describe('renameFile', () => {
79
79
  it('should rename a file', () => {
80
- const context = new Context(`${__dirname}/migrations/fixtures`);
80
+ const context = new Context(`${__dirname}/fixtures`);
81
81
  context.renameFile('foo/bar.ts', 'new-file.txt');
82
82
  expect(context.listChanges()).toEqual({
83
83
  'new-file.txt': { content: "console.log('foo/bar.ts');\n", changeType: 'add' },
@@ -102,20 +102,20 @@ describe('Context', () => {
102
102
 
103
103
  describe('readDir', () => {
104
104
  it('should read the directory', () => {
105
- const context = new Context(`${__dirname}/migrations/fixtures`);
105
+ const context = new Context(`${__dirname}/fixtures`);
106
106
  const files = context.readDir('foo');
107
107
  expect(files).toEqual(['foo/bar.ts', 'foo/baz.ts']);
108
108
  });
109
109
 
110
110
  it('should filter out deleted files', () => {
111
- const context = new Context(`${__dirname}/migrations/fixtures`);
111
+ const context = new Context(`${__dirname}/fixtures`);
112
112
  context.deleteFile('foo/bar.ts');
113
113
  const files = context.readDir('foo');
114
114
  expect(files).toEqual(['foo/baz.ts']);
115
115
  });
116
116
 
117
117
  it('should include files that are only added to the context', () => {
118
- const context = new Context(`${__dirname}/migrations/fixtures`);
118
+ const context = new Context(`${__dirname}/fixtures`);
119
119
  context.addFile('foo/foo.txt', '');
120
120
  const files = context.readDir('foo');
121
121
  expect(files).toEqual(['foo/bar.ts', 'foo/baz.ts', 'foo/foo.txt']);
@@ -124,7 +124,7 @@ describe('Context', () => {
124
124
 
125
125
  describe('normalisePath', () => {
126
126
  it('should normalise the path', () => {
127
- const context = new Context(`${__dirname}/migrations/fixtures`);
127
+ const context = new Context(`${__dirname}/fixtures`);
128
128
  expect(context.normalisePath('foo/bar.ts')).toEqual('foo/bar.ts');
129
129
  expect(context.normalisePath('./foo/bar.ts')).toEqual('foo/bar.ts');
130
130
  expect(context.normalisePath('/foo/bar.ts')).toEqual('foo/bar.ts');
@@ -133,12 +133,12 @@ describe('Context', () => {
133
133
 
134
134
  describe('hasChanges', () => {
135
135
  it('should return FALSE if the context has no changes', () => {
136
- const context = new Context(`${__dirname}/migrations/fixtures`);
136
+ const context = new Context(`${__dirname}/fixtures`);
137
137
  expect(context.hasChanges()).toEqual(false);
138
138
  });
139
139
 
140
140
  it('should return TRUE if the context has changes', () => {
141
- const context = new Context(`${__dirname}/migrations/fixtures`);
141
+ const context = new Context(`${__dirname}/fixtures`);
142
142
 
143
143
  context.addFile('foo.ts', '');
144
144
 
@@ -1,8 +1,6 @@
1
1
  import { constants, accessSync, readFileSync, readdirSync } from 'node:fs';
2
2
  import { relative, normalize, join, dirname } from 'node:path';
3
- import { debug } from '../utils/utils.cli.js';
4
-
5
- const codemodsDebug = debug.extend('codemods');
3
+ import { migrationsDebug } from './utils.js';
6
4
 
7
5
  export type ContextFile = Record<
8
6
  string,
@@ -60,7 +58,7 @@ export class Context {
60
58
  if (originalContent !== content) {
61
59
  this.files[path] = { content, changeType: 'update' };
62
60
  } else {
63
- codemodsDebug(`Context.updateFile() - no updates for ${filePath}`);
61
+ migrationsDebug(`Context.updateFile() - no updates for ${filePath}`);
64
62
  }
65
63
  }
66
64
 
@@ -1,27 +1,22 @@
1
- import { flushChanges, formatFiles } from '../utils.js';
1
+ import { vi } from 'vitest';
2
2
  import { getMigrationsToRun, runMigration, runMigrations } from './manager.js';
3
-
4
- import { Context } from '../context.js';
5
- import { MigrationMeta } from './migrations.js';
6
- import { gitCommitNoVerify } from '../../utils/utils.git.js';
7
3
  import migrationFixtures from './fixtures/migrations.js';
8
- import { printChanges } from './utils.js';
9
- import { setRootConfig } from '../../utils/utils.config.js';
10
- import { vi } from 'vitest';
4
+ import { Context } from './context.js';
5
+ import { gitCommitNoVerify } from '../utils/utils.git.js';
6
+ import { flushChanges, printChanges, formatFiles } from './utils.js';
7
+ import { setRootConfig } from '../utils/utils.config.js';
8
+ import { MigrationMeta } from './migrations.js';
11
9
 
12
10
  vi.mock('./utils.js', () => ({
11
+ flushChanges: vi.fn(),
13
12
  printChanges: vi.fn(),
14
13
  migrationsDebug: vi.fn(),
15
- }));
16
-
17
- vi.mock('../utils.js', () => ({
18
- flushChanges: vi.fn(),
19
14
  formatFiles: vi.fn(),
20
15
  installNPMDependencies: vi.fn(),
21
16
  }));
22
17
 
23
18
  // Silence terminal output during tests.
24
- vi.mock('../../utils/utils.console.js', () => ({
19
+ vi.mock('../utils/utils.console.js', () => ({
25
20
  output: {
26
21
  log: vi.fn(),
27
22
  addHorizontalLine: vi.fn(),
@@ -30,10 +25,10 @@ vi.mock('../../utils/utils.console.js', () => ({
30
25
  },
31
26
  }));
32
27
 
33
- vi.mock('../../utils/utils.config.js', () => ({
28
+ vi.mock('../utils/utils.config.js', () => ({
34
29
  setRootConfig: vi.fn(),
35
30
  }));
36
- vi.mock('../../utils/utils.git.js', () => ({
31
+ vi.mock('../utils/utils.git.js', () => ({
37
32
  gitCommitNoVerify: vi.fn(),
38
33
  }));
39
34
 
@@ -1,14 +1,13 @@
1
+ import { satisfies, gte } from 'semver';
2
+ import { Context } from './context.js';
1
3
  import defaultMigrations, { MigrationMeta } from './migrations.js';
2
- import { flushChanges, formatFiles, installNPMDependencies } from '../utils.js';
3
- import { gte, satisfies } from 'semver';
4
- import { migrationsDebug, printChanges } from './utils.js';
4
+ import { flushChanges, printChanges, migrationsDebug, formatFiles, installNPMDependencies } from './utils.js';
5
+ import { gitCommitNoVerify } from '../utils/utils.git.js';
6
+ import { setRootConfig } from '../utils/utils.config.js';
7
+ import { output } from '../utils/utils.console.js';
8
+ import { CURRENT_APP_VERSION } from '../utils/utils.version.js';
5
9
 
6
- import { CURRENT_APP_VERSION } from '../../utils/utils.version.js';
7
- import { Context } from '../context.js';
8
- import type { MigrationModule } from '../types.js';
9
- import { gitCommitNoVerify } from '../../utils/utils.git.js';
10
- import { output } from '../../utils/utils.console.js';
11
- import { setRootConfig } from '../../utils/utils.config.js';
10
+ export type MigrationFn = (context: Context) => Context | Promise<Context>;
12
11
 
13
12
  export function getMigrationsToRun(
14
13
  fromVersion: string,
@@ -77,7 +76,7 @@ export async function runMigrations(migrations: Record<string, MigrationMeta>, o
77
76
  }
78
77
 
79
78
  export async function runMigration(migration: MigrationMeta, context: Context): Promise<Context> {
80
- const module = (await import(migration.migrationScript)) as MigrationModule;
79
+ const module: { default: MigrationFn } = await import(migration.migrationScript);
81
80
 
82
81
  return module.default(context);
83
82
  }
@@ -1,4 +1,4 @@
1
- import { LEGACY_UPDATE_CUTOFF_VERSION } from '../../constants.js';
1
+ import { LEGACY_UPDATE_CUTOFF_VERSION } from '../constants.js';
2
2
 
3
3
  export type MigrationMeta = {
4
4
  version: string;
@@ -10,6 +10,8 @@ type Migrations = {
10
10
  migrations: Record<string, MigrationMeta>;
11
11
  };
12
12
 
13
+ // Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It was used to force migrations to run
14
+ // for those written before the switch to updates as migrations.
13
15
  export default {
14
16
  migrations: {
15
17
  '001-update-grafana-compose-extend': {
@@ -33,7 +35,10 @@ export default {
33
35
  description: 'Migrate eslint config to flat config format and update devDependencies to latest versions.',
34
36
  migrationScript: './scripts/004-eslint9-flat-config.js',
35
37
  },
36
- // Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It is only used above to force migrations to run
37
- // for those written before the switch to updates as migrations.
38
+ '005-react-18-3': {
39
+ version: '6.1.7-beta.1',
40
+ description: 'Update React 18.0.0 to 18.3.1.',
41
+ migrationScript: './scripts/005-react-18-3.js',
42
+ },
38
43
  },
39
44
  } as Migrations;
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { Context } from '../../context.js';
2
+ import { Context } from '../context.js';
3
3
  import migrate from './001-update-grafana-compose-extend.js';
4
4
  import { parse, stringify } from 'yaml';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { resolve } from 'node:path';
2
- import { type Context } from '../../context.js';
2
+ import { type Context } from '../context.js';
3
3
  import { Node, Pair, parseDocument, Scalar, stringify, visit, YAMLMap, Document, YAMLSeq, visitorFn } from 'yaml';
4
4
 
5
5
  export default async function migrate(context: Context) {
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { Context } from '../../context.js';
2
+ import { Context } from '../context.js';
3
3
  import migrate from './002-update-is-compatible-workflow.js';
4
4
  import { parse } from 'yaml';
5
5
 
@@ -1,4 +1,4 @@
1
- import { type Context } from '../../context.js';
1
+ import { type Context } from '../context.js';
2
2
  import { parseDocument, stringify, YAMLSeq } from 'yaml';
3
3
 
4
4
  export default async function migrate(context: Context) {
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
  import migrate from './003-update-eslint-deprecation-rule.js';
3
- import { Context } from '../../context.js';
3
+ import { Context } from '../context.js';
4
4
 
5
5
  describe('003-update-eslint-deprecation-rule', () => {
6
6
  it('should not update ESLint config if no deprecation rule is present', () => {
@@ -1,5 +1,5 @@
1
- import type { Context } from '../../context.js';
2
- import { addDependenciesToPackageJson, removeDependenciesFromPackageJson } from '../../utils.js';
1
+ import type { Context } from '../context.js';
2
+ import { addDependenciesToPackageJson, removeDependenciesFromPackageJson } from '../utils.js';
3
3
 
4
4
  export default function migrate(context: Context) {
5
5
  if (context.doesFileExist('.config/.eslintrc') && context.doesFileExist('package.json')) {
@@ -1,5 +1,5 @@
1
1
  import migrate from './004-eslint9-flat-config.js';
2
- import { Context } from '../../context.js';
2
+ import { Context } from '../context.js';
3
3
 
4
4
  describe('004-eslint9-flat-config', () => {
5
5
  describe('migration', () => {
@@ -5,9 +5,8 @@ import { parse } from 'jsonc-parser';
5
5
  import minimist from 'minimist';
6
6
  import { dirname, relative, resolve } from 'node:path';
7
7
  import * as recast from 'recast';
8
- import type { Context } from '../../context.js';
9
- import { addDependenciesToPackageJson } from '../../utils.js';
10
- import { migrationsDebug } from '../utils.js';
8
+ import type { Context } from '../context.js';
9
+ import { addDependenciesToPackageJson, migrationsDebug } from '../utils.js';
11
10
 
12
11
  type Imports = Map<string, { name?: string; bindings?: string[] }>;
13
12