@grafana/create-plugin 6.2.0-canary.2233.19133609453.0 → 6.2.0-canary.2233.19368311379.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 +61 -0
- package/CONTRIBUTING.md +3 -0
- package/dist/codemods/additions/additions.js +8 -8
- package/dist/codemods/additions/scripts/example-addition.js +19 -33
- package/dist/codemods/migrations/manager.js +13 -40
- package/dist/codemods/migrations/migrations.js +34 -25
- package/dist/codemods/migrations/scripts/004-eslint9-flat-config.js +1 -2
- package/dist/codemods/migrations/scripts/005-react-18-3.js +20 -0
- package/dist/codemods/migrations/scripts/example-migration.js +7 -3
- package/dist/codemods/runner.js +38 -0
- package/dist/codemods/schema-parser.js +20 -0
- package/dist/codemods/utils.js +15 -6
- package/dist/commands/add.command.js +24 -55
- package/dist/commands/update.command.js +7 -41
- package/dist/utils/utils.checks.js +40 -0
- package/dist/utils/utils.config.js +1 -16
- package/package.json +3 -2
- package/src/codemods/additions/additions.test.ts +12 -0
- package/src/codemods/additions/additions.ts +9 -22
- package/src/codemods/additions/scripts/example-addition.test.ts +14 -33
- package/src/codemods/additions/scripts/example-addition.ts +27 -44
- package/src/codemods/migrations/fixtures/migrations.ts +19 -18
- package/src/codemods/migrations/manager.test.ts +67 -73
- package/src/codemods/migrations/manager.ts +17 -50
- package/src/codemods/migrations/migrations.test.ts +8 -5
- package/src/codemods/migrations/migrations.ts +38 -34
- package/src/codemods/migrations/scripts/004-eslint9-flat-config.ts +2 -2
- package/src/codemods/migrations/scripts/005-react-18-3.test.ts +145 -0
- package/src/codemods/migrations/scripts/005-react-18-3.ts +19 -0
- package/src/codemods/migrations/scripts/example-migration.test.ts +1 -1
- package/src/codemods/migrations/scripts/example-migration.ts +20 -3
- package/src/codemods/runner.ts +57 -0
- package/src/codemods/schema-parser.ts +27 -0
- package/src/codemods/types.ts +9 -14
- package/src/codemods/{migrations/utils.test.ts → utils.test.ts} +8 -7
- package/src/codemods/utils.ts +28 -36
- package/src/commands/add.command.ts +26 -62
- package/src/commands/update.command.ts +8 -47
- package/src/migrations/migrations.ts +44 -0
- package/src/utils/utils.checks.ts +47 -0
- package/src/utils/utils.config.ts +1 -28
- package/templates/common/_package.json +7 -5
- package/templates/github/workflows/bundle-stats.yml +1 -1
- package/templates/github/workflows/ci.yml +11 -11
- package/templates/github/workflows/cp-update.yml +9 -14
- package/templates/github/workflows/is-compatible.yml +3 -3
- package/templates/github/workflows/release.yml +1 -1
- package/vitest.config.ts +12 -0
- package/dist/codemods/additions/manager.js +0 -115
- package/dist/codemods/additions/utils.js +0 -10
- package/dist/codemods/migrations/utils.js +0 -10
- package/src/codemods/additions/manager.ts +0 -145
- package/src/codemods/additions/utils.ts +0 -12
- package/src/codemods/migrations/utils.ts +0 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,64 @@
|
|
|
1
|
+
# v6.1.11 (Fri Nov 14 2025)
|
|
2
|
+
|
|
3
|
+
#### 🐛 Bug Fix
|
|
4
|
+
|
|
5
|
+
- chore(deps): update create-plugin template github actions [#2301](https://github.com/grafana/plugin-tools/pull/2301) ([@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot]))
|
|
6
|
+
- chore(deps): update dependency @grafana/eslint-config to v9 [#2285](https://github.com/grafana/plugin-tools/pull/2285) ([@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot]) [@jackw](https://github.com/jackw))
|
|
7
|
+
|
|
8
|
+
#### Authors: 2
|
|
9
|
+
|
|
10
|
+
- [@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot])
|
|
11
|
+
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# v6.1.10 (Thu Nov 13 2025)
|
|
16
|
+
|
|
17
|
+
#### 🐛 Bug Fix
|
|
18
|
+
|
|
19
|
+
- Feat: use latest create-plugin-update workflow [#2299](https://github.com/grafana/plugin-tools/pull/2299) ([@jackw](https://github.com/jackw))
|
|
20
|
+
|
|
21
|
+
#### Authors: 1
|
|
22
|
+
|
|
23
|
+
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
# v6.1.9 (Wed Nov 12 2025)
|
|
28
|
+
|
|
29
|
+
#### 🐛 Bug Fix
|
|
30
|
+
|
|
31
|
+
- Create plugin: use react 18.3.x [#2283](https://github.com/grafana/plugin-tools/pull/2283) ([@jackw](https://github.com/jackw))
|
|
32
|
+
|
|
33
|
+
#### Authors: 1
|
|
34
|
+
|
|
35
|
+
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
# v6.1.8 (Fri Nov 07 2025)
|
|
40
|
+
|
|
41
|
+
### Release Notes
|
|
42
|
+
|
|
43
|
+
#### chore(deps): update grafana patch dependencies ([#2217](https://github.com/grafana/plugin-tools/pull/2217))
|
|
44
|
+
|
|
45
|
+
<details>
|
|
46
|
+
<summary>grafana/grafana (@​grafana/data)</summary>
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
#### 🐛 Bug Fix
|
|
51
|
+
|
|
52
|
+
- Create plugin: fix permissions issue in cp-update workflow [#2281](https://github.com/grafana/plugin-tools/pull/2281) ([@jackw](https://github.com/jackw))
|
|
53
|
+
- 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]))
|
|
54
|
+
|
|
55
|
+
#### Authors: 2
|
|
56
|
+
|
|
57
|
+
- [@renovate-sh-app[bot]](https://github.com/renovate-sh-app[bot])
|
|
58
|
+
- Jack Westbrook ([@jackw](https://github.com/jackw))
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
1
62
|
# v6.1.7 (Mon Nov 03 2025)
|
|
2
63
|
|
|
3
64
|
: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.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { resolveScriptPath } from '../utils.js';
|
|
2
|
+
|
|
3
|
+
var defaultAdditions = [
|
|
4
|
+
{
|
|
5
|
+
name: "example-addition",
|
|
6
|
+
description: "Example addition demonstrating Valibot schema with type inference",
|
|
7
|
+
scriptPath: resolveScriptPath(import.meta.url, "./scripts/example-addition.js")
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
-
var defaultAdditions = { additions };
|
|
9
|
+
];
|
|
10
10
|
|
|
11
11
|
export { defaultAdditions as default };
|
|
@@ -1,25 +1,20 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
1
2
|
import { addDependenciesToPackageJson } from '../../utils.js';
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
featureName: argv["feature-name"] || "myFeature",
|
|
18
|
-
enabled: argv.enabled === "true" || argv.enabled === true
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
function migrate(context, options = { featureName: "myFeature", enabled: true }) {
|
|
22
|
-
const { featureName, enabled } = options;
|
|
4
|
+
const schema = v.object({
|
|
5
|
+
featureName: v.pipe(
|
|
6
|
+
v.string(),
|
|
7
|
+
v.minLength(3, "Feature name must be at least 3 characters"),
|
|
8
|
+
v.maxLength(50, "Feature name must be at most 50 characters")
|
|
9
|
+
),
|
|
10
|
+
enabled: v.optional(v.boolean(), true),
|
|
11
|
+
port: v.optional(
|
|
12
|
+
v.pipe(v.number(), v.minValue(1e3, "Port must be at least 1000"), v.maxValue(65535, "Port must be at most 65535"))
|
|
13
|
+
),
|
|
14
|
+
frameworks: v.optional(v.array(v.string()), ["react"])
|
|
15
|
+
});
|
|
16
|
+
function exampleAddition(context, options) {
|
|
17
|
+
const { featureName, enabled, port, frameworks } = options;
|
|
23
18
|
const rawPkgJson = context.getFile("./package.json") ?? "{}";
|
|
24
19
|
const packageJson = JSON.parse(rawPkgJson);
|
|
25
20
|
if (packageJson.scripts && !packageJson.scripts["example-script"]) {
|
|
@@ -27,23 +22,14 @@ function migrate(context, options = { featureName: "myFeature", enabled: true })
|
|
|
27
22
|
context.updateFile("./package.json", JSON.stringify(packageJson, null, 2));
|
|
28
23
|
}
|
|
29
24
|
addDependenciesToPackageJson(context, {}, { "example-dev-dep": "^1.0.0" });
|
|
30
|
-
if (!context.doesFileExist("./src/config.json")) {
|
|
31
|
-
const config = {
|
|
32
|
-
features: {
|
|
33
|
-
[featureName]: {
|
|
34
|
-
enabled,
|
|
35
|
-
description: "Example feature configuration"
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
context.addFile("./src/config.json", JSON.stringify(config, null, 2));
|
|
40
|
-
}
|
|
41
25
|
if (!context.doesFileExist(`./src/features/${featureName}.ts`)) {
|
|
42
26
|
const featureCode = `export const ${featureName} = {
|
|
43
27
|
name: '${featureName}',
|
|
44
28
|
enabled: ${enabled},
|
|
29
|
+
port: ${port ?? 3e3},
|
|
30
|
+
frameworks: ${JSON.stringify(frameworks)},
|
|
45
31
|
init() {
|
|
46
|
-
console.log('${featureName} initialized');
|
|
32
|
+
console.log('${featureName} initialized on port ${port ?? 3e3}');
|
|
47
33
|
},
|
|
48
34
|
};
|
|
49
35
|
`;
|
|
@@ -58,4 +44,4 @@ function migrate(context, options = { featureName: "myFeature", enabled: true })
|
|
|
58
44
|
return context;
|
|
59
45
|
}
|
|
60
46
|
|
|
61
|
-
export {
|
|
47
|
+
export { exampleAddition as default, schema };
|
|
@@ -1,49 +1,26 @@
|
|
|
1
1
|
import defaultMigrations from './migrations.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { migrationsDebug, printChanges } from './utils.js';
|
|
2
|
+
import { runCodemod } from '../runner.js';
|
|
3
|
+
import { satisfies, gte } from 'semver';
|
|
5
4
|
import { CURRENT_APP_VERSION } from '../../utils/utils.version.js';
|
|
6
|
-
import { Context } from '../context.js';
|
|
7
5
|
import { gitCommitNoVerify } from '../../utils/utils.git.js';
|
|
8
6
|
import { output } from '../../utils/utils.console.js';
|
|
9
7
|
import { setRootConfig } from '../../utils/utils.config.js';
|
|
10
8
|
|
|
11
|
-
function getMigrationsToRun(fromVersion, toVersion, migrations = defaultMigrations
|
|
9
|
+
function getMigrationsToRun(fromVersion, toVersion, migrations = defaultMigrations) {
|
|
12
10
|
const semverRange = `${fromVersion} - ${toVersion}`;
|
|
13
|
-
|
|
14
|
-
return gte(a
|
|
15
|
-
})
|
|
16
|
-
if (satisfies(meta.version, semverRange)) {
|
|
17
|
-
acc[key] = meta;
|
|
18
|
-
}
|
|
19
|
-
return acc;
|
|
20
|
-
}, {});
|
|
21
|
-
return migrationsToRun;
|
|
11
|
+
return migrations.filter((meta) => satisfies(meta.version, semverRange)).sort((a, b) => {
|
|
12
|
+
return gte(a.version, b.version) ? 1 : -1;
|
|
13
|
+
});
|
|
22
14
|
}
|
|
23
15
|
async function runMigrations(migrations, options = {}) {
|
|
24
|
-
const
|
|
25
|
-
const migrationList = Object.entries(migrations).map(
|
|
26
|
-
([key, migrationMeta]) => `${key} (${migrationMeta.description})`
|
|
27
|
-
);
|
|
16
|
+
const migrationList = migrations.map((meta) => `${meta.name} (${meta.description})`);
|
|
28
17
|
const migrationListBody = migrationList.length > 0 ? output.bulletList(migrationList) : ["No migrations to run."];
|
|
29
18
|
output.log({ title: "Running the following migrations:", body: migrationListBody });
|
|
30
|
-
for (const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
migrationsDebug("%O", context.listChanges());
|
|
36
|
-
await formatFiles(context);
|
|
37
|
-
flushChanges(context);
|
|
38
|
-
printChanges(context, key, migration);
|
|
39
|
-
installNPMDependencies(context);
|
|
40
|
-
if (shouldCommit) {
|
|
41
|
-
await gitCommitNoVerify(`chore: run create-plugin migration - ${key} (${migration.migrationScript})`);
|
|
42
|
-
}
|
|
43
|
-
} catch (error) {
|
|
44
|
-
if (error instanceof Error) {
|
|
45
|
-
throw new Error(`Error running migration "${key} (${migration.migrationScript})": ${error.message}`);
|
|
46
|
-
}
|
|
19
|
+
for (const migration of migrations) {
|
|
20
|
+
const context = await runCodemod(migration, options.codemodOptions);
|
|
21
|
+
const shouldCommit = options.commitEachMigration && context.hasChanges();
|
|
22
|
+
if (shouldCommit) {
|
|
23
|
+
await gitCommitNoVerify(`chore: run create-plugin migration - ${migration.name} (${migration.scriptPath})`);
|
|
47
24
|
}
|
|
48
25
|
}
|
|
49
26
|
setRootConfig({ version: CURRENT_APP_VERSION });
|
|
@@ -51,9 +28,5 @@ async function runMigrations(migrations, options = {}) {
|
|
|
51
28
|
await gitCommitNoVerify(`chore: update .config/.cprc.json to version ${CURRENT_APP_VERSION}.`);
|
|
52
29
|
}
|
|
53
30
|
}
|
|
54
|
-
async function runMigration(migration, context) {
|
|
55
|
-
const module = await import(migration.migrationScript);
|
|
56
|
-
return module.default(context);
|
|
57
|
-
}
|
|
58
31
|
|
|
59
|
-
export { getMigrationsToRun,
|
|
32
|
+
export { getMigrationsToRun, runMigrations };
|
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
import { LEGACY_UPDATE_CUTOFF_VERSION } from '../../constants.js';
|
|
2
|
+
import { resolveScriptPath } from '../utils.js';
|
|
2
3
|
|
|
3
|
-
var defaultMigrations =
|
|
4
|
-
|
|
5
|
-
"001-update-grafana-compose-extend"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
4
|
+
var defaultMigrations = [
|
|
5
|
+
{
|
|
6
|
+
name: "001-update-grafana-compose-extend",
|
|
7
|
+
version: LEGACY_UPDATE_CUTOFF_VERSION,
|
|
8
|
+
description: "Update ./docker-compose.yaml to extend from ./.config/docker-compose-base.yaml.",
|
|
9
|
+
scriptPath: resolveScriptPath(import.meta.url, "./scripts/001-update-grafana-compose-extend.js")
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: "002-update-is-compatible-workflow",
|
|
13
|
+
version: LEGACY_UPDATE_CUTOFF_VERSION,
|
|
14
|
+
description: "Update ./.github/workflows/is-compatible.yml to use is-compatible github action instead of calling levitate directly",
|
|
15
|
+
scriptPath: resolveScriptPath(import.meta.url, "./scripts/002-update-is-compatible-workflow.js")
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "003-update-eslint-deprecation-rule",
|
|
19
|
+
version: LEGACY_UPDATE_CUTOFF_VERSION,
|
|
20
|
+
description: "Replace deprecated eslint-plugin-deprecation with @typescript-eslint/no-deprecated rule.",
|
|
21
|
+
scriptPath: resolveScriptPath(import.meta.url, "./scripts/003-update-eslint-deprecation-rule.js")
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "004-eslint9-flat-config",
|
|
25
|
+
version: LEGACY_UPDATE_CUTOFF_VERSION,
|
|
26
|
+
description: "Migrate eslint config to flat config format and update devDependencies to latest versions.",
|
|
27
|
+
scriptPath: resolveScriptPath(import.meta.url, "./scripts/004-eslint9-flat-config.js")
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "005-react-18-3",
|
|
31
|
+
version: "6.1.9",
|
|
32
|
+
description: "Update React and ReactDOM 18.x versions to ^18.3.0 to surface React 19 compatibility issues.",
|
|
33
|
+
scriptPath: resolveScriptPath(import.meta.url, "./scripts/005-react-18-3.js")
|
|
27
34
|
}
|
|
28
|
-
|
|
35
|
+
// Do not use LEGACY_UPDATE_CUTOFF_VERSION for new migrations. It is only used above to force migrations to run
|
|
36
|
+
// for those written before the switch to updates as migrations.
|
|
37
|
+
];
|
|
29
38
|
|
|
30
39
|
export { defaultMigrations as default };
|
|
@@ -5,7 +5,6 @@ import minimist from 'minimist';
|
|
|
5
5
|
import { resolve, dirname, relative } from 'node:path';
|
|
6
6
|
import * as recast from 'recast';
|
|
7
7
|
import { addDependenciesToPackageJson } from '../../utils.js';
|
|
8
|
-
import { migrationsDebug } from '../utils.js';
|
|
9
8
|
|
|
10
9
|
const { builders } = recast.types;
|
|
11
10
|
const legacyKeysToCopy = ["rules", "settings"];
|
|
@@ -318,7 +317,7 @@ function getIgnorePaths(context) {
|
|
|
318
317
|
}
|
|
319
318
|
}
|
|
320
319
|
} catch (error) {
|
|
321
|
-
|
|
320
|
+
console.log("Error parsing package.json: %s", error);
|
|
322
321
|
}
|
|
323
322
|
}
|
|
324
323
|
return Array.from(result);
|
|
@@ -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.0" }, { "@types/react": "^18.3.0" });
|
|
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.0" }, { "@types/react-dom": "^18.3.0" });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return context;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { migrate as default };
|
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
function migrate(context) {
|
|
1
|
+
function migrate(context, options = {}) {
|
|
2
|
+
const { profile = false, skipBackup = false, verbose = false } = options;
|
|
3
|
+
if (verbose) {
|
|
4
|
+
console.log("Running migration with options:", options);
|
|
5
|
+
}
|
|
2
6
|
const rawPkgJson = context.getFile("./package.json") ?? "{}";
|
|
3
7
|
const packageJson = JSON.parse(rawPkgJson);
|
|
4
8
|
if (packageJson.scripts && packageJson.scripts.build) {
|
|
5
9
|
const buildScript = packageJson.scripts.build;
|
|
6
10
|
const pattern = /(webpack.+-c\s.+\.ts)\s(.+)/;
|
|
7
|
-
if (pattern.test(buildScript) && !buildScript.includes("--profile")) {
|
|
11
|
+
if (profile && pattern.test(buildScript) && !buildScript.includes("--profile")) {
|
|
8
12
|
packageJson.scripts.build = buildScript.replace(pattern, `$1 --profile $2`);
|
|
9
13
|
}
|
|
10
14
|
context.updateFile("./package.json", JSON.stringify(packageJson, null, 2));
|
|
11
15
|
}
|
|
12
|
-
if (context.doesFileExist("./src/README.md")) {
|
|
16
|
+
if (!skipBackup && context.doesFileExist("./src/README.md")) {
|
|
13
17
|
context.deleteFile("./src/README.md");
|
|
14
18
|
}
|
|
15
19
|
if (!context.doesFileExist("./src/foo.json")) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Context } from './context.js';
|
|
2
|
+
import { formatFiles, flushChanges, printChanges, installNPMDependencies } from './utils.js';
|
|
3
|
+
import { parseAndValidateOptions } from './schema-parser.js';
|
|
4
|
+
import { output } from '../utils/utils.console.js';
|
|
5
|
+
|
|
6
|
+
async function runCodemod(codemod, options) {
|
|
7
|
+
const codemodModule = await import(codemod.scriptPath);
|
|
8
|
+
if (!codemodModule.default || typeof codemodModule.default !== "function") {
|
|
9
|
+
throw new Error(`Codemod ${codemod.name} must export a default function`);
|
|
10
|
+
}
|
|
11
|
+
let codemodOptions = {};
|
|
12
|
+
if (options && codemodModule.schema) {
|
|
13
|
+
codemodOptions = parseAndValidateOptions(options, codemodModule.schema);
|
|
14
|
+
}
|
|
15
|
+
const basePath = process.cwd();
|
|
16
|
+
const context = new Context(basePath);
|
|
17
|
+
try {
|
|
18
|
+
output.log({
|
|
19
|
+
title: `Running ${codemod.name}`,
|
|
20
|
+
body: [codemod.description]
|
|
21
|
+
});
|
|
22
|
+
const updatedContext = await codemodModule.default(context, codemodOptions);
|
|
23
|
+
await formatFiles(updatedContext);
|
|
24
|
+
flushChanges(updatedContext);
|
|
25
|
+
printChanges(updatedContext, codemod.name, codemod.description);
|
|
26
|
+
installNPMDependencies(updatedContext);
|
|
27
|
+
return updatedContext;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof Error) {
|
|
30
|
+
const newError = new Error(`Error running ${codemod.name}: ${error.message}`);
|
|
31
|
+
newError.cause = error;
|
|
32
|
+
throw newError;
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { runCodemod };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as v from 'valibot';
|
|
2
|
+
|
|
3
|
+
function parseAndValidateOptions(options, schema) {
|
|
4
|
+
try {
|
|
5
|
+
return v.parse(schema, options);
|
|
6
|
+
} catch (error) {
|
|
7
|
+
if (v.isValiError(error)) {
|
|
8
|
+
const formattedErrors = error.issues.map((issue) => {
|
|
9
|
+
const path = issue.path?.map((p) => p.key).join(".") || "";
|
|
10
|
+
return ` --${path}: ${issue.message}`;
|
|
11
|
+
}).join("\n");
|
|
12
|
+
throw new Error(`Invalid flag(s) provided:
|
|
13
|
+
|
|
14
|
+
${formattedErrors}`);
|
|
15
|
+
}
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { parseAndValidateOptions };
|
package/dist/codemods/utils.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dirname, resolve, join } from 'node:path';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { output } from '../utils/utils.console.js';
|
|
6
6
|
import { getPackageManagerWithFallback, getPackageManagerSilentInstallCmd } from '../utils/utils.packageManager.js';
|
|
7
7
|
import { execSync } from 'node:child_process';
|
|
8
|
-
import { gt, clean, coerce } from 'semver';
|
|
8
|
+
import { gte, gt, clean, coerce } from 'semver';
|
|
9
|
+
import { fileURLToPath } from 'node:url';
|
|
9
10
|
|
|
10
|
-
function printChanges(context, key,
|
|
11
|
+
function printChanges(context, key, description) {
|
|
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} (${
|
|
24
|
+
output.logSingleLine(`${key} (${description})`);
|
|
24
25
|
if (lines.length === 0) {
|
|
25
26
|
output.logSingleLine("No changes were made");
|
|
26
27
|
} else {
|
|
@@ -178,7 +179,7 @@ const DIST_TAGS = {
|
|
|
178
179
|
next: 1,
|
|
179
180
|
latest: 0
|
|
180
181
|
};
|
|
181
|
-
function isVersionGreater(incomingVersion, existingVersion) {
|
|
182
|
+
function isVersionGreater(incomingVersion, existingVersion, orEqualTo = false) {
|
|
182
183
|
const incomingIsDistTag = incomingVersion in DIST_TAGS;
|
|
183
184
|
const existingIsDistTag = existingVersion in DIST_TAGS;
|
|
184
185
|
if (incomingIsDistTag && existingIsDistTag) {
|
|
@@ -192,6 +193,9 @@ function isVersionGreater(incomingVersion, existingVersion) {
|
|
|
192
193
|
if (!incomingSemver || !existingSemver) {
|
|
193
194
|
return true;
|
|
194
195
|
}
|
|
196
|
+
if (orEqualTo) {
|
|
197
|
+
return gte(incomingSemver, existingSemver);
|
|
198
|
+
}
|
|
195
199
|
return gt(incomingSemver, existingSemver);
|
|
196
200
|
}
|
|
197
201
|
function cleanSemver(version) {
|
|
@@ -200,5 +204,10 @@ function cleanSemver(version) {
|
|
|
200
204
|
function sortObjectByKeys(obj) {
|
|
201
205
|
return Object.keys(obj).sort().reduce((acc, key) => ({ ...acc, [key]: obj[key] }), {});
|
|
202
206
|
}
|
|
207
|
+
function resolveScriptPath(callerUrl, relativePath) {
|
|
208
|
+
const __filename = fileURLToPath(callerUrl);
|
|
209
|
+
const __dirname = dirname(__filename);
|
|
210
|
+
return resolve(__dirname, relativePath);
|
|
211
|
+
}
|
|
203
212
|
|
|
204
|
-
export { addDependenciesToPackageJson, flushChanges, formatFiles, installNPMDependencies, isVersionGreater, printChanges, readJsonFile, removeDependenciesFromPackageJson };
|
|
213
|
+
export { addDependenciesToPackageJson, flushChanges, formatFiles, installNPMDependencies, isVersionGreater, printChanges, readJsonFile, removeDependenciesFromPackageJson, resolveScriptPath };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import defaultAdditions from '../codemods/additions/additions.js';
|
|
2
|
+
import { runCodemod } from '../codemods/runner.js';
|
|
3
|
+
import { getPackageManagerFromUserAgent, getPackageManagerExecCmd } from '../utils/utils.packageManager.js';
|
|
4
|
+
import { performPreCodemodChecks } from '../utils/utils.checks.js';
|
|
4
5
|
import { output } from '../utils/utils.console.js';
|
|
5
6
|
|
|
6
7
|
const add = async (argv) => {
|
|
@@ -9,9 +10,24 @@ const add = async (argv) => {
|
|
|
9
10
|
await showAdditionsHelp();
|
|
10
11
|
process.exit(1);
|
|
11
12
|
}
|
|
12
|
-
await
|
|
13
|
+
await performPreCodemodChecks(argv);
|
|
13
14
|
try {
|
|
14
|
-
|
|
15
|
+
const addition = defaultAdditions.find((addition2) => addition2.name === subCommand);
|
|
16
|
+
if (!addition) {
|
|
17
|
+
const additionsList = defaultAdditions.map((addition2) => addition2.name);
|
|
18
|
+
throw new Error(`Unknown addition: ${subCommand}
|
|
19
|
+
|
|
20
|
+
Available additions: ${additionsList.join(", ")}`);
|
|
21
|
+
}
|
|
22
|
+
output.log({
|
|
23
|
+
title: `Running addition: ${addition.name}`,
|
|
24
|
+
body: [addition.description]
|
|
25
|
+
});
|
|
26
|
+
const { _, $0, ...codemodOptions } = argv;
|
|
27
|
+
await runCodemod(addition, codemodOptions);
|
|
28
|
+
output.success({
|
|
29
|
+
title: `Successfully added ${addition.name} to your plugin.`
|
|
30
|
+
});
|
|
15
31
|
} catch (error) {
|
|
16
32
|
if (error instanceof Error) {
|
|
17
33
|
output.error({
|
|
@@ -23,64 +39,17 @@ const add = async (argv) => {
|
|
|
23
39
|
}
|
|
24
40
|
};
|
|
25
41
|
async function showAdditionsHelp() {
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
Object.values(availableAdditions).map(async (addition) => {
|
|
29
|
-
let info = `${addition.name} - ${addition.description}`;
|
|
30
|
-
const flags = await getAdditionFlags(addition);
|
|
31
|
-
if (flags.length > 0) {
|
|
32
|
-
const flagDocs = flags.map((flag) => {
|
|
33
|
-
const req = flag.required ? " (required)" : " (optional)";
|
|
34
|
-
return ` --${flag.name}: ${flag.description}${req}`;
|
|
35
|
-
});
|
|
36
|
-
info += "\n" + flagDocs.join("\n");
|
|
37
|
-
}
|
|
38
|
-
return info;
|
|
39
|
-
})
|
|
40
|
-
);
|
|
42
|
+
const additionsList = defaultAdditions.map((addition) => addition.name);
|
|
43
|
+
const { packageManagerName, packageManagerVersion } = getPackageManagerFromUserAgent();
|
|
41
44
|
output.error({
|
|
42
45
|
title: "No addition specified",
|
|
43
46
|
body: [
|
|
44
|
-
|
|
47
|
+
`Usage: ${getPackageManagerExecCmd(packageManagerName, packageManagerVersion)} add <addition-name> [options]`,
|
|
45
48
|
"",
|
|
46
49
|
"Available additions:",
|
|
47
50
|
...output.bulletList(additionsList)
|
|
48
51
|
]
|
|
49
52
|
});
|
|
50
53
|
}
|
|
51
|
-
async function performPreAddChecks(argv) {
|
|
52
|
-
if (!await isGitDirectory() && !argv.force) {
|
|
53
|
-
output.error({
|
|
54
|
-
title: "You are not inside a git directory",
|
|
55
|
-
body: [
|
|
56
|
-
`In order to proceed please run ${output.formatCode("git init")} in the root of your project and commit your changes.`,
|
|
57
|
-
`(This check is necessary to make sure that the changes are easy to revert and don't interfere with any changes you currently have.`,
|
|
58
|
-
`In case you want to proceed as is please use the ${output.formatCode("--force")} flag.)`
|
|
59
|
-
]
|
|
60
|
-
});
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
if (!await isGitDirectoryClean() && !argv.force) {
|
|
64
|
-
output.error({
|
|
65
|
-
title: "Please clean your repository working tree before adding features.",
|
|
66
|
-
body: [
|
|
67
|
-
"Commit your changes or stash them.",
|
|
68
|
-
`(This check is necessary to make sure that the changes are easy to revert and don't mess with any changes you currently have.`,
|
|
69
|
-
`In case you want to proceed as is please use the ${output.formatCode("--force")} flag.)`
|
|
70
|
-
]
|
|
71
|
-
});
|
|
72
|
-
process.exit(1);
|
|
73
|
-
}
|
|
74
|
-
if (!isPluginDirectory() && !argv.force) {
|
|
75
|
-
output.error({
|
|
76
|
-
title: "Are you inside a plugin directory?",
|
|
77
|
-
body: [
|
|
78
|
-
`We couldn't find a "src/plugin.json" file under your current directory.`,
|
|
79
|
-
`(Please make sure to run this command from the root of your plugin folder. In case you want to proceed as is please use the ${output.formatCode("--force")} flag.)`
|
|
80
|
-
]
|
|
81
|
-
});
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
54
|
|
|
86
55
|
export { add };
|