@grafana/create-plugin 6.2.0-canary.2233.18946524692.0 → 6.2.0-canary.2233.19095991328.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 (59) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/{additions → codemods/additions}/manager.js +23 -24
  3. package/dist/{additions → codemods/additions}/scripts/add-i18n.js +2 -2
  4. package/dist/codemods/additions/utils.js +10 -0
  5. package/dist/{migrations → codemods}/context.js +3 -2
  6. package/dist/{migrations → codemods/migrations}/manager.js +8 -7
  7. package/dist/{migrations → codemods/migrations}/migrations.js +1 -1
  8. package/dist/{migrations → codemods/migrations}/scripts/003-update-eslint-deprecation-rule.js +1 -1
  9. package/dist/{migrations → codemods/migrations}/scripts/004-eslint9-flat-config.js +2 -1
  10. package/dist/codemods/migrations/utils.js +10 -0
  11. package/dist/{migrations → codemods}/utils.js +3 -17
  12. package/dist/commands/add.command.js +2 -2
  13. package/dist/commands/update.command.js +1 -1
  14. package/package.json +3 -5
  15. package/src/{additions → codemods/additions}/additions.ts +1 -0
  16. package/src/{additions → codemods/additions}/manager.ts +27 -40
  17. package/src/{additions → codemods/additions}/scripts/add-i18n.test.ts +1 -1
  18. package/src/{additions → codemods/additions}/scripts/add-i18n.ts +5 -5
  19. package/src/codemods/additions/utils.ts +12 -0
  20. package/src/{migrations → codemods}/context.test.ts +10 -10
  21. package/src/{migrations → codemods}/context.ts +4 -2
  22. package/src/{migrations → codemods/migrations}/manager.test.ts +15 -10
  23. package/src/{migrations → codemods/migrations}/manager.ts +10 -9
  24. package/src/{migrations → codemods/migrations}/migrations.ts +1 -1
  25. package/src/{migrations → codemods/migrations}/scripts/001-update-grafana-compose-extend.test.ts +1 -1
  26. package/src/{migrations → codemods/migrations}/scripts/001-update-grafana-compose-extend.ts +1 -1
  27. package/src/{migrations → codemods/migrations}/scripts/002-update-is-compatible-workflow.test.ts +1 -1
  28. package/src/{migrations → codemods/migrations}/scripts/002-update-is-compatible-workflow.ts +1 -1
  29. package/src/{migrations → codemods/migrations}/scripts/003-update-eslint-deprecation-rule.test.ts +1 -1
  30. package/src/{migrations → codemods/migrations}/scripts/003-update-eslint-deprecation-rule.ts +2 -2
  31. package/src/{migrations → codemods/migrations}/scripts/004-eslint9-flat-config.test.ts +1 -1
  32. package/src/{migrations → codemods/migrations}/scripts/004-eslint9-flat-config.ts +3 -2
  33. package/src/{migrations → codemods/migrations}/scripts/example-migration.test.ts +1 -1
  34. package/src/{migrations → codemods/migrations}/scripts/example-migration.ts +1 -1
  35. package/src/{migrations → codemods/migrations}/utils.test.ts +4 -4
  36. package/src/codemods/migrations/utils.ts +12 -0
  37. package/src/codemods/types.ts +21 -0
  38. package/src/{migrations → codemods}/utils.ts +35 -22
  39. package/src/commands/add.command.ts +2 -2
  40. package/src/commands/update.command.ts +1 -1
  41. package/src/utils/utils.config.ts +3 -3
  42. package/templates/common/.config/docker-compose-base.yaml +1 -1
  43. package/templates/common/_package.json +7 -7
  44. package/templates/github/workflows/bundle-stats.yml +1 -1
  45. package/templates/github/workflows/ci.yml +4 -4
  46. package/templates/github/workflows/cp-update.yml +1 -1
  47. package/templates/github/workflows/is-compatible.yml +1 -1
  48. package/templates/github/workflows/release.yml +1 -1
  49. package/dist/additions/utils.js +0 -28
  50. package/src/additions/utils.ts +0 -39
  51. /package/dist/{additions → codemods/additions}/additions.js +0 -0
  52. /package/dist/{migrations → codemods/migrations}/scripts/001-update-grafana-compose-extend.js +0 -0
  53. /package/dist/{migrations → codemods/migrations}/scripts/002-update-is-compatible-workflow.js +0 -0
  54. /package/dist/{migrations → codemods/migrations}/scripts/example-migration.js +0 -0
  55. /package/src/{migrations → codemods/migrations}/fixtures/foo/bar.ts +0 -0
  56. /package/src/{migrations → codemods/migrations}/fixtures/foo/baz.ts +0 -0
  57. /package/src/{migrations → codemods/migrations}/fixtures/migrations.ts +0 -0
  58. /package/src/{migrations → codemods/migrations}/migrations.test.ts +0 -0
  59. /package/src/{migrations → codemods}/test-utils.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ # v6.1.7 (Mon Nov 03 2025)
2
+
3
+ :tada: This release contains work from a new contributor! :tada:
4
+
5
+ Thank you, Steffen Gebert ([@StephenKing](https://github.com/StephenKing)), for all your work!
6
+
7
+ #### 🐛 Bug Fix
8
+
9
+ - Fix workflow references [#2261](https://github.com/grafana/plugin-tools/pull/2261) ([@StephenKing](https://github.com/StephenKing))
10
+
11
+ #### Authors: 1
12
+
13
+ - Steffen Gebert ([@StephenKing](https://github.com/StephenKing))
14
+
15
+ ---
16
+
17
+ # v6.1.6 (Mon Nov 03 2025)
18
+
19
+ #### 🐛 Bug Fix
20
+
21
+ - chore(deps): update dependency @grafana/plugin-e2e to v3 [#2259](https://github.com/grafana/plugin-tools/pull/2259) ([@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot]))
22
+
23
+ #### Authors: 1
24
+
25
+ - [@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot])
26
+
27
+ ---
28
+
1
29
  # v6.1.5 (Tue Oct 28 2025)
2
30
 
3
31
  #### 🐛 Bug Fix
@@ -1,10 +1,9 @@
1
1
  import { additionsDebug, printChanges } from './utils.js';
2
2
  import defaultAdditions from './additions.js';
3
- import { getConfig, isFeatureEnabled, setFeatureFlag } from '../utils/utils.config.js';
4
- import { Context } from '../migrations/context.js';
5
- import { gitCommitNoVerify } from '../utils/utils.git.js';
6
- import { output } from '../utils/utils.console.js';
7
- import { formatFiles, flushChanges, installNPMDependencies } from '../migrations/utils.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';
8
7
 
9
8
  function getAvailableAdditions(additions = defaultAdditions.additions) {
10
9
  return additions;
@@ -12,24 +11,25 @@ function getAvailableAdditions(additions = defaultAdditions.additions) {
12
11
  function getAdditionByName(name, additions = defaultAdditions.additions) {
13
12
  return additions[name];
14
13
  }
15
- async function getAdditionFlags(addition) {
14
+ async function loadAdditionModule(addition) {
16
15
  try {
17
16
  const module = await import(addition.scriptPath);
18
- return module.flags || [];
17
+ return module;
19
18
  } catch (error) {
20
- return [];
19
+ additionsDebug('Failed to load addition module for "%s" from %s: %O', addition.name, addition.scriptPath, error);
20
+ return null;
21
21
  }
22
22
  }
23
+ async function getAdditionFlags(addition) {
24
+ const module = await loadAdditionModule(addition);
25
+ return module?.flags || [];
26
+ }
23
27
  async function parseAdditionFlags(addition, argv) {
24
- try {
25
- const module = await import(addition.scriptPath);
26
- if (module.parseFlags && typeof module.parseFlags === "function") {
27
- return module.parseFlags(argv);
28
- }
29
- return {};
30
- } catch (error) {
31
- return {};
28
+ const module = await loadAdditionModule(addition);
29
+ if (module?.parseFlags) {
30
+ return module.parseFlags(argv);
32
31
  }
32
+ return {};
33
33
  }
34
34
  async function validateAdditionOptions(addition, options) {
35
35
  const flags = await getAdditionFlags(addition);
@@ -56,7 +56,7 @@ Example: npx @grafana/create-plugin add ${addition.name} --${missingFlags[0]}=va
56
56
  );
57
57
  }
58
58
  }
59
- async function runAdditionByName(additionName, argv, runOptions = {}) {
59
+ async function runAdditionByName(additionName, argv) {
60
60
  const addition = getAdditionByName(additionName);
61
61
  if (!addition) {
62
62
  const availableAdditions = getAvailableAdditions();
@@ -67,9 +67,9 @@ Available additions: ${additionsList.join(", ")}`);
67
67
  }
68
68
  const options = await parseAdditionFlags(addition, argv);
69
69
  await validateAdditionOptions(addition, options);
70
- await runAddition(addition, options, runOptions);
70
+ await runAddition(addition, options);
71
71
  }
72
- async function runAddition(addition, additionOptions = {}, runOptions = {}) {
72
+ async function runAddition(addition, additionOptions = {}) {
73
73
  const basePath = process.cwd();
74
74
  const config = getConfig();
75
75
  if (isFeatureEnabled(config.features, addition.featureName)) {
@@ -86,7 +86,6 @@ async function runAddition(addition, additionOptions = {}, runOptions = {}) {
86
86
  try {
87
87
  const context = new Context(basePath);
88
88
  const updatedContext = await executeAddition(addition, context, additionOptions);
89
- const shouldCommit = runOptions.commitChanges && updatedContext.hasChanges();
90
89
  additionsDebug(`context for "${addition.name} (${addition.scriptPath})":`);
91
90
  additionsDebug("%O", updatedContext.listChanges());
92
91
  await formatFiles(updatedContext);
@@ -95,9 +94,6 @@ async function runAddition(addition, additionOptions = {}, runOptions = {}) {
95
94
  installNPMDependencies(updatedContext);
96
95
  await setFeatureFlag(addition.featureName, true);
97
96
  additionsDebug(`Set feature flag '${addition.featureName}' to true in .cprc.json`);
98
- if (shouldCommit) {
99
- await gitCommitNoVerify(`chore: add ${addition.name} support via create-plugin`);
100
- }
101
97
  output.success({
102
98
  title: `Successfully added ${addition.name} to your plugin.`
103
99
  });
@@ -109,7 +105,10 @@ async function runAddition(addition, additionOptions = {}, runOptions = {}) {
109
105
  }
110
106
  }
111
107
  async function executeAddition(addition, context, options = {}) {
112
- const module = await import(addition.scriptPath);
108
+ const module = await loadAdditionModule(addition);
109
+ if (!module) {
110
+ throw new Error(`Failed to load addition module for ${addition.name}`);
111
+ }
113
112
  return module.default(context, options);
114
113
  }
115
114
 
@@ -1,8 +1,8 @@
1
1
  import * as recast from 'recast';
2
- import { additionsDebug } from '../utils.js';
3
2
  import { coerce, gte } from 'semver';
4
3
  import { parseDocument, stringify } from 'yaml';
5
- import { addDependenciesToPackageJson } from '../../migrations/utils.js';
4
+ import { addDependenciesToPackageJson } from '../../utils.js';
5
+ import { additionsDebug } from '../utils.js';
6
6
 
7
7
  const { builders } = recast.types;
8
8
  const flags = [
@@ -0,0 +1,10 @@
1
+ import { debug } from '../../utils/utils.cli.js';
2
+ import { printChanges as printChanges$1 } from '../utils.js';
3
+
4
+ const additionsDebug = debug.extend("additions");
5
+ function printChanges(context, key, addition) {
6
+ additionsDebug("printChanges for addition: %s", key);
7
+ printChanges$1(context, key, addition);
8
+ }
9
+
10
+ export { additionsDebug, printChanges };
@@ -1,10 +1,11 @@
1
1
  import { accessSync, constants, readFileSync, readdirSync } from 'node:fs';
2
2
  import { join, dirname, normalize, relative } from 'node:path';
3
- import { migrationsDebug } from './utils.js';
3
+ import { debug } from '../utils/utils.cli.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");
8
9
  class Context {
9
10
  constructor(basePath) {
10
11
  __publicField(this, "files", {});
@@ -41,7 +42,7 @@ class Context {
41
42
  if (originalContent !== content) {
42
43
  this.files[path] = { content, changeType: "update" };
43
44
  } else {
44
- migrationsDebug(`Context.updateFile() - no updates for ${filePath}`);
45
+ codemodsDebug(`Context.updateFile() - no updates for ${filePath}`);
45
46
  }
46
47
  }
47
48
  doesFileExist(filePath) {
@@ -1,11 +1,12 @@
1
- import { gte, satisfies } from 'semver';
2
- import { Context } from './context.js';
3
1
  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';
2
+ import { formatFiles, flushChanges, installNPMDependencies } from '../utils.js';
3
+ 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';
9
10
 
10
11
  function getMigrationsToRun(fromVersion, toVersion, migrations = defaultMigrations.migrations) {
11
12
  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: {
@@ -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,7 +4,8 @@ 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, migrationsDebug } from '../utils.js';
7
+ import { addDependenciesToPackageJson } from '../../utils.js';
8
+ import { migrationsDebug } from '../utils.js';
8
9
 
9
10
  const { builders } = recast.types;
10
11
  const legacyKeysToCopy = ["rules", "settings"];
@@ -0,0 +1,10 @@
1
+ import { debug } from '../../utils/utils.cli.js';
2
+ import { printChanges as printChanges$1 } from '../utils.js';
3
+
4
+ const migrationsDebug = debug.extend("migrations");
5
+ function printChanges(context, key, migration) {
6
+ migrationsDebug("printChanges for migration: %s", key);
7
+ printChanges$1(context, key, migration);
8
+ }
9
+
10
+ export { migrationsDebug, printChanges };
@@ -1,14 +1,13 @@
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';
5
4
  import chalk from 'chalk';
6
5
  import { output } from '../utils/utils.console.js';
7
6
  import { getPackageManagerWithFallback, getPackageManagerSilentInstallCmd } from '../utils/utils.packageManager.js';
8
7
  import { execSync } from 'node:child_process';
9
8
  import { gt, clean, coerce } from 'semver';
10
9
 
11
- function printChanges(context, key, migration) {
10
+ function printChanges(context, key, meta) {
12
11
  const changes = context.listChanges();
13
12
  const lines = [];
14
13
  for (const [filePath, { changeType }] of Object.entries(changes)) {
@@ -21,7 +20,7 @@ function printChanges(context, key, migration) {
21
20
  }
22
21
  }
23
22
  output.addHorizontalLine("gray");
24
- output.logSingleLine(`${key} (${migration.description})`);
23
+ output.logSingleLine(`${key} (${meta.description})`);
25
24
  if (lines.length === 0) {
26
25
  output.logSingleLine("No changes were made");
27
26
  } else {
@@ -43,7 +42,6 @@ function flushChanges(context) {
43
42
  }
44
43
  }
45
44
  }
46
- const migrationsDebug = debug.extend("migrations");
47
45
  async function formatFiles(context) {
48
46
  let prettier;
49
47
  const require = createRequire(import.meta.url);
@@ -120,14 +118,10 @@ function addDependenciesToPackageJson(context, dependencies, devDependencies = {
120
118
  if (currentDeps[dep]) {
121
119
  if (isVersionGreater(newVersion, currentDeps[dep])) {
122
120
  currentDeps[dep] = newVersion;
123
- } else {
124
- migrationsDebug("would downgrade dependency %s to %s", dep, newVersion);
125
121
  }
126
122
  } else if (currentDevDeps[dep]) {
127
123
  if (isVersionGreater(newVersion, currentDevDeps[dep])) {
128
124
  currentDevDeps[dep] = newVersion;
129
- } else {
130
- migrationsDebug("would downgrade devDependency %s to %s", dep, newVersion);
131
125
  }
132
126
  } else {
133
127
  currentDeps[dep] = newVersion;
@@ -137,14 +131,10 @@ function addDependenciesToPackageJson(context, dependencies, devDependencies = {
137
131
  if (currentDeps[dep]) {
138
132
  if (isVersionGreater(newVersion, currentDeps[dep])) {
139
133
  currentDeps[dep] = newVersion;
140
- } else {
141
- migrationsDebug("would downgrade dependency %s to %s", dep, newVersion);
142
134
  }
143
135
  } else if (currentDevDeps[dep]) {
144
136
  if (isVersionGreater(newVersion, currentDevDeps[dep])) {
145
137
  currentDevDeps[dep] = newVersion;
146
- } else {
147
- migrationsDebug("would downgrade devDependency %s to %s", dep, newVersion);
148
138
  }
149
139
  } else {
150
140
  currentDevDeps[dep] = newVersion;
@@ -161,7 +151,6 @@ function addDependenciesToPackageJson(context, dependencies, devDependencies = {
161
151
  ...Object.keys(sortedDeps).length > 0 && { dependencies: sortedDeps },
162
152
  ...Object.keys(sortedDevDeps).length > 0 && { devDependencies: sortedDevDeps }
163
153
  };
164
- migrationsDebug("updated package.json", updatedPackageJson);
165
154
  context.updateFile(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2));
166
155
  }
167
156
  function removeDependenciesFromPackageJson(context, dependencies, devDependencies = [], packageJsonPath = "package.json") {
@@ -170,21 +159,18 @@ function removeDependenciesFromPackageJson(context, dependencies, devDependencie
170
159
  for (const dep of dependencies) {
171
160
  if (currentPackageJson.dependencies?.[dep]) {
172
161
  delete currentPackageJson.dependencies[dep];
173
- migrationsDebug("removed dependency %s", dep);
174
162
  hasChanges = true;
175
163
  }
176
164
  }
177
165
  for (const dep of devDependencies) {
178
166
  if (currentPackageJson.devDependencies?.[dep]) {
179
167
  delete currentPackageJson.devDependencies[dep];
180
- migrationsDebug("removed devDependency %s", dep);
181
168
  hasChanges = true;
182
169
  }
183
170
  }
184
171
  if (!hasChanges) {
185
172
  return;
186
173
  }
187
- migrationsDebug("updated package.json", currentPackageJson);
188
174
  context.updateFile(packageJsonPath, JSON.stringify(currentPackageJson, null, 2));
189
175
  }
190
176
  const DIST_TAGS = {
@@ -215,4 +201,4 @@ function sortObjectByKeys(obj) {
215
201
  return Object.keys(obj).sort().reduce((acc, key) => ({ ...acc, [key]: obj[key] }), {});
216
202
  }
217
203
 
218
- export { addDependenciesToPackageJson, flushChanges, formatFiles, installNPMDependencies, isVersionGreater, migrationsDebug, printChanges, readJsonFile, removeDependenciesFromPackageJson };
204
+ export { addDependenciesToPackageJson, flushChanges, formatFiles, installNPMDependencies, isVersionGreater, printChanges, readJsonFile, removeDependenciesFromPackageJson };
@@ -1,4 +1,4 @@
1
- import { runAdditionByName, getAvailableAdditions, getAdditionFlags } from '../additions/manager.js';
1
+ import { runAdditionByName, getAvailableAdditions, getAdditionFlags } from '../codemods/additions/manager.js';
2
2
  import { isGitDirectory, isGitDirectoryClean } from '../utils/utils.git.js';
3
3
  import { isPluginDirectory } from '../utils/utils.plugin.js';
4
4
  import { output } from '../utils/utils.console.js';
@@ -11,7 +11,7 @@ const add = async (argv) => {
11
11
  }
12
12
  await performPreAddChecks(argv);
13
13
  try {
14
- await runAdditionByName(subCommand, argv, { commitChanges: argv.commit });
14
+ await runAdditionByName(subCommand, argv);
15
15
  } catch (error) {
16
16
  if (error instanceof Error) {
17
17
  output.error({
@@ -1,4 +1,4 @@
1
- import { getMigrationsToRun, runMigrations } from '../migrations/manager.js';
1
+ import { getMigrationsToRun, runMigrations } from '../codemods/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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafana/create-plugin",
3
- "version": "6.2.0-canary.2233.18946524692.0",
3
+ "version": "6.2.0-canary.2233.19095991328.0",
4
4
  "repository": {
5
5
  "directory": "packages/create-plugin",
6
6
  "url": "https://github.com/grafana/plugin-tools"
@@ -49,9 +49,7 @@
49
49
  "@types/semver": "^7.7.1",
50
50
  "@types/tmp": "^0.2.6",
51
51
  "@types/which": "^3.0.4",
52
- "eslint-plugin-react": "^7.37.5",
53
- "eslint-plugin-react-hooks": "^5.2.0",
54
- "tmp": "^0.2.4"
52
+ "tmp": "^0.2.5"
55
53
  },
56
54
  "overrides": {
57
55
  "@types/marked-terminal": {
@@ -61,5 +59,5 @@
61
59
  "engines": {
62
60
  "node": ">=20"
63
61
  },
64
- "gitHead": "66533b5a682753ffda37f33a185e8fa2fe2c8383"
62
+ "gitHead": "4b094c74fad3475760af9185821ccd0340c4c073"
65
63
  }
@@ -16,6 +16,7 @@ const additions = {
16
16
 
17
17
  export default { additions };
18
18
 
19
+ // extract feature names for type-safe FeatureFlags in utils.config.ts
19
20
  type AdditionValues = (typeof additions)[keyof typeof additions];
20
21
  export type AdditionFeatureName = AdditionValues['featureName'];
21
22
 
@@ -1,19 +1,14 @@
1
- import { additionsDebug, flushChanges, formatFiles, installNPMDependencies, printChanges } from './utils.js';
1
+ import type { AdditionModule, FlagDefinition } from '../types.js';
2
+ import { additionsDebug, printChanges } from './utils.js';
2
3
  import defaultAdditions, { AdditionMeta } from './additions.js';
3
- import { getConfig, isFeatureEnabled, setFeatureFlag } from '../utils/utils.config.js';
4
+ import { flushChanges, formatFiles, installNPMDependencies } from '../utils.js';
5
+ import { getConfig, isFeatureEnabled, setFeatureFlag } from '../../utils/utils.config.js';
4
6
 
5
- import { Context } from '../migrations/context.js';
6
- import { gitCommitNoVerify } from '../utils/utils.git.js';
7
- import { output } from '../utils/utils.console.js';
8
-
9
- export type AdditionFn = (context: Context, options?: AdditionOptions) => Context | Promise<Context>;
7
+ import { Context } from '../context.js';
8
+ import { output } from '../../utils/utils.console.js';
10
9
 
11
10
  export type AdditionOptions = Record<string, any>;
12
11
 
13
- type RunAdditionOptions = {
14
- commitChanges?: boolean;
15
- };
16
-
17
12
  export function getAvailableAdditions(
18
13
  additions: Record<string, AdditionMeta> = defaultAdditions.additions
19
14
  ): Record<string, AdditionMeta> {
@@ -27,25 +22,27 @@ export function getAdditionByName(
27
22
  return additions[name];
28
23
  }
29
24
 
30
- export async function getAdditionFlags(addition: AdditionMeta): Promise<any[]> {
25
+ async function loadAdditionModule(addition: AdditionMeta): Promise<AdditionModule | null> {
31
26
  try {
32
- const module = await import(addition.scriptPath);
33
- return module.flags || [];
27
+ const module = (await import(addition.scriptPath)) as AdditionModule;
28
+ return module;
34
29
  } catch (error) {
35
- return [];
30
+ additionsDebug('Failed to load addition module for "%s" from %s: %O', addition.name, addition.scriptPath, error);
31
+ return null;
36
32
  }
37
33
  }
38
34
 
35
+ export async function getAdditionFlags(addition: AdditionMeta): Promise<FlagDefinition[]> {
36
+ const module = await loadAdditionModule(addition);
37
+ return module?.flags || [];
38
+ }
39
+
39
40
  export async function parseAdditionFlags(addition: AdditionMeta, argv: any): Promise<AdditionOptions> {
40
- try {
41
- const module = await import(addition.scriptPath);
42
- if (module.parseFlags && typeof module.parseFlags === 'function') {
43
- return module.parseFlags(argv);
44
- }
45
- return {};
46
- } catch (error) {
47
- return {};
41
+ const module = await loadAdditionModule(addition);
42
+ if (module?.parseFlags) {
43
+ return module.parseFlags(argv);
48
44
  }
45
+ return {};
49
46
  }
50
47
 
51
48
  async function validateAdditionOptions(addition: AdditionMeta, options: AdditionOptions): Promise<void> {
@@ -77,11 +74,7 @@ async function validateAdditionOptions(addition: AdditionMeta, options: Addition
77
74
  }
78
75
  }
79
76
 
80
- export async function runAdditionByName(
81
- additionName: string,
82
- argv: any,
83
- runOptions: RunAdditionOptions = {}
84
- ): Promise<void> {
77
+ export async function runAdditionByName(additionName: string, argv: any): Promise<void> {
85
78
  const addition = getAdditionByName(additionName);
86
79
  if (!addition) {
87
80
  const availableAdditions = getAvailableAdditions();
@@ -91,14 +84,10 @@ export async function runAdditionByName(
91
84
 
92
85
  const options = await parseAdditionFlags(addition, argv);
93
86
  await validateAdditionOptions(addition, options);
94
- await runAddition(addition, options, runOptions);
87
+ await runAddition(addition, options);
95
88
  }
96
89
 
97
- export async function runAddition(
98
- addition: AdditionMeta,
99
- additionOptions: AdditionOptions = {},
100
- runOptions: RunAdditionOptions = {}
101
- ): Promise<void> {
90
+ export async function runAddition(addition: AdditionMeta, additionOptions: AdditionOptions = {}): Promise<void> {
102
91
  const basePath = process.cwd();
103
92
 
104
93
  // Check if the feature is already enabled
@@ -119,7 +108,6 @@ export async function runAddition(
119
108
  try {
120
109
  const context = new Context(basePath);
121
110
  const updatedContext = await executeAddition(addition, context, additionOptions);
122
- const shouldCommit = runOptions.commitChanges && updatedContext.hasChanges();
123
111
 
124
112
  additionsDebug(`context for "${addition.name} (${addition.scriptPath})":`);
125
113
  additionsDebug('%O', updatedContext.listChanges());
@@ -133,10 +121,6 @@ export async function runAddition(
133
121
  await setFeatureFlag(addition.featureName, true);
134
122
  additionsDebug(`Set feature flag '${addition.featureName}' to true in .cprc.json`);
135
123
 
136
- if (shouldCommit) {
137
- await gitCommitNoVerify(`chore: add ${addition.name} support via create-plugin`);
138
- }
139
-
140
124
  output.success({
141
125
  title: `Successfully added ${addition.name} to your plugin.`,
142
126
  });
@@ -153,6 +137,9 @@ export async function executeAddition(
153
137
  context: Context,
154
138
  options: AdditionOptions = {}
155
139
  ): Promise<Context> {
156
- const module: { default: AdditionFn } = await import(addition.scriptPath);
140
+ const module = await loadAdditionModule(addition);
141
+ if (!module) {
142
+ throw new Error(`Failed to load addition module for ${addition.name}`);
143
+ }
157
144
  return module.default(context, options);
158
145
  }
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from 'vitest';
2
2
 
3
- import { Context } from '../../migrations/context.js';
3
+ import { Context } from '../../context.js';
4
4
  import migrate from './add-i18n.js';
5
5
 
6
6
  describe('add-i18n', () => {
@@ -1,10 +1,12 @@
1
1
  import * as recast from 'recast';
2
2
 
3
- import { addDependenciesToPackageJson, additionsDebug } from '../utils.js';
4
3
  import { coerce, gte } from 'semver';
5
4
  import { parseDocument, stringify } from 'yaml';
6
5
 
7
- import type { Context } from '../../migrations/context.js';
6
+ import type { Context } from '../../context.js';
7
+ import type { FlagDefinition } from '../../types.js';
8
+ import { addDependenciesToPackageJson } from '../../utils.js';
9
+ import { additionsDebug } from '../utils.js';
8
10
 
9
11
  const { builders } = recast.types;
10
12
 
@@ -12,8 +14,7 @@ export type I18nOptions = {
12
14
  locales: string[];
13
15
  };
14
16
 
15
- // Flag schema for CLI
16
- export const flags = [
17
+ export const flags: FlagDefinition[] = [
17
18
  {
18
19
  name: 'locales',
19
20
  description: 'Comma-separated list of locales (e.g., en-US,es-ES)',
@@ -21,7 +22,6 @@ export const flags = [
21
22
  },
22
23
  ];
23
24
 
24
- // Parse CLI flags to options
25
25
  export function parseFlags(argv: any): I18nOptions {
26
26
  return {
27
27
  locales: argv.locales ? argv.locales.split(',').map((l: string) => l.trim()) : [],
@@ -0,0 +1,12 @@
1
+ import type { AdditionMeta } from './additions.js';
2
+ import type { Context } from '../context.js';
3
+ import { debug } from '../../utils/utils.cli.js';
4
+ import { printChanges as sharedPrintChanges } from '../utils.js';
5
+
6
+ export const additionsDebug = debug.extend('additions');
7
+
8
+ // addition-specific wrapper for printChanges.
9
+ export function printChanges(context: Context, key: string, addition: AdditionMeta) {
10
+ additionsDebug('printChanges for addition: %s', key);
11
+ sharedPrintChanges(context, key, addition);
12
+ }
@@ -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}/fixtures`);
6
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
19
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
26
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
80
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
105
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
111
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
118
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
127
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
136
+ const context = new Context(`${__dirname}/migrations/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}/fixtures`);
141
+ const context = new Context(`${__dirname}/migrations/fixtures`);
142
142
 
143
143
  context.addFile('foo.ts', '');
144
144