@carbon/upgrade 10.15.0 → 10.17.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 (43) hide show
  1. package/README.md +12 -16
  2. package/bin/carbon-upgrade.js +4 -8
  3. package/cli.js +56459 -0
  4. package/package.json +18 -9
  5. package/transforms/ARCHITECTURE.md +47 -0
  6. package/transforms/__testfixtures__/icons-react-size-prop-object-key.input.js +16 -0
  7. package/transforms/__testfixtures__/icons-react-size-prop-object-key.output.js +16 -0
  8. package/transforms/__testfixtures__/icons-react-size-prop-rename.input.js +44 -0
  9. package/transforms/__testfixtures__/icons-react-size-prop-rename.output.js +44 -0
  10. package/transforms/__testfixtures__/icons-react-size-prop-with-prop.input.js +19 -0
  11. package/transforms/__testfixtures__/icons-react-size-prop-with-prop.output.js +22 -0
  12. package/transforms/__testfixtures__/size-prop-update.input.js +143 -0
  13. package/transforms/__testfixtures__/size-prop-update.output.js +143 -0
  14. package/transforms/__testfixtures__/small-to-size-prop.input.js +11 -0
  15. package/transforms/__testfixtures__/small-to-size-prop.output.js +11 -0
  16. package/transforms/__testfixtures__/sort-prop-types.input.js +7 -0
  17. package/transforms/__testfixtures__/sort-prop-types.output.js +7 -0
  18. package/transforms/__testfixtures__/sort-prop-types2.input.js +7 -0
  19. package/transforms/__testfixtures__/sort-prop-types2.output.js +7 -0
  20. package/transforms/__testfixtures__/update-carbon-components-react-import-to-scoped.input.js +8 -0
  21. package/transforms/__testfixtures__/update-carbon-components-react-import-to-scoped.output.js +8 -0
  22. package/transforms/__tests__/icons-react-size-prop.js +64 -0
  23. package/transforms/__tests__/size-prop-update-test.js +12 -0
  24. package/transforms/__tests__/small-to-size-test.js +12 -0
  25. package/transforms/__tests__/sort-prop-types-test.js +13 -0
  26. package/transforms/__tests__/update-carbon-components-react-import-to-scoped.js +12 -0
  27. package/transforms/icons-react-size-prop.js +324 -0
  28. package/transforms/size-prop-update.js +140 -0
  29. package/transforms/small-to-size-prop.js +56 -0
  30. package/transforms/sort-prop-types.js +88 -0
  31. package/transforms/update-carbon-components-react-import-to-scoped.js +33 -0
  32. package/src/cli.js +0 -100
  33. package/src/error.js +0 -21
  34. package/src/hash.js +0 -87
  35. package/src/migration.js +0 -85
  36. package/src/migrations/index.js +0 -41
  37. package/src/planner.js +0 -58
  38. package/src/project/__tests__/project-test.js +0 -52
  39. package/src/project/__tests__/workspace-test.js +0 -92
  40. package/src/project/index.js +0 -16
  41. package/src/project/project.js +0 -92
  42. package/src/project/workspace.js +0 -172
  43. package/src/runner.js +0 -76
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2020
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ 'use strict';
9
+
10
+ const defaultOptions = {
11
+ quote: 'single',
12
+ trailingComma: true,
13
+ };
14
+
15
+ function transform(fileInfo, api, options) {
16
+ const printOptions = options.printOptions || defaultOptions;
17
+ const j = api.jscodeshift;
18
+ const root = j(fileInfo.source);
19
+
20
+ root
21
+ .find(j.AssignmentExpression, {
22
+ left: {
23
+ type: 'MemberExpression',
24
+ property: {
25
+ name: 'propTypes',
26
+ },
27
+ },
28
+ })
29
+ .forEach((path) => {
30
+ path.node.right.properties.sort((a, b) => {
31
+ if (a.type === 'Property' && b.type === 'Property') {
32
+ if (getPropName(a) > getPropName(b)) {
33
+ return 1;
34
+ }
35
+ return -1;
36
+ }
37
+
38
+ if (a.type === 'SpreadElement' && b.type === 'SpreadElement') {
39
+ if (getPropName(a) > getPropName(b)) {
40
+ return 1;
41
+ }
42
+ return -1;
43
+ }
44
+
45
+ if (a.type === 'SpreadElement') {
46
+ return -1;
47
+ }
48
+
49
+ return 1;
50
+ });
51
+ });
52
+
53
+ root
54
+ .find(j.ClassProperty, {
55
+ key: {
56
+ name: 'propTypes',
57
+ },
58
+ })
59
+ .forEach((path) => {
60
+ path.node.value.properties.sort((a, b) => {
61
+ if (getPropName(a) > getPropName(b)) {
62
+ return 1;
63
+ }
64
+ return -1;
65
+ });
66
+ });
67
+
68
+ function getPropName(node) {
69
+ if (node.type === 'SpreadElement') {
70
+ return node.argument.name;
71
+ }
72
+
73
+ if (node.type === 'Property') {
74
+ if (node.key.type === 'Identifier') {
75
+ return node.key.name;
76
+ }
77
+ if (node.key.type === 'Literal') {
78
+ return node.key.value;
79
+ }
80
+ }
81
+
82
+ throw new Error(`Unknown node of type: ${node.type}`);
83
+ }
84
+
85
+ return root.toSource(printOptions);
86
+ }
87
+
88
+ module.exports = transform;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright IBM Corp. 2016, 2020
3
+ *
4
+ * This source code is licensed under the Apache-2.0 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * Rewrites imports from 'carbon-components-react' to '@carbon/react'
8
+ *
9
+ * Transforms:
10
+ *
11
+ * import { Button } from 'carbon-components-react';
12
+ *
13
+ * Into:
14
+ *
15
+ * import { Button } from "@carbon/react";
16
+ */
17
+
18
+ export const parser = 'babel';
19
+
20
+ export default function transformer(file, api) {
21
+ const j = api.jscodeshift;
22
+
23
+ return j(file.source)
24
+ .find(j.ImportDeclaration, {
25
+ source: {
26
+ value: 'carbon-components-react',
27
+ },
28
+ })
29
+ .forEach((path) => {
30
+ path.get('source').replace(j.stringLiteral('@carbon/react'));
31
+ })
32
+ .toSource();
33
+ }
package/src/cli.js DELETED
@@ -1,100 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const cli = require('yargs');
11
- const isGitClean = require('is-git-clean');
12
- const packageJson = require('../package.json');
13
- const { UpgradeError } = require('./error');
14
- const { Migration } = require('./migration');
15
- const { Planner } = require('./planner');
16
- const { Project } = require('./project');
17
- const { Runner } = require('./runner');
18
-
19
- async function main({ argv, cwd }) {
20
- cli.scriptName(packageJson.name).version(packageJson.version);
21
-
22
- cli
23
- .option('verbose', {
24
- default: false,
25
- describe: 'display the full output while running a command',
26
- })
27
- .option('write', {
28
- alias: 'w',
29
- describe: 'update the files with changes found by running the migration',
30
- default: false,
31
- })
32
- .option('ignore', {
33
- alias: 'i',
34
- describe:
35
- 'provide a list of glob pattern for directories you would like ignored',
36
- default: [],
37
- array: true,
38
- });
39
-
40
- cli.usage('Usage: $0 [options]').command(
41
- '$0',
42
- 'run to upgrade your project',
43
- {},
44
- run(async (args) => {
45
- const { ignore, verbose, write } = args;
46
- const options = {
47
- cwd: cwd(),
48
- ignore,
49
- verbose,
50
- write,
51
- };
52
-
53
- const project = await Project.detect(options.cwd);
54
- const migrationsByWorkspace = await Migration.getMigrationsByWorkspace(
55
- Array.from(project.getWorkspaces()),
56
- Migration.getMigrations()
57
- );
58
- const migrationsToRun = await Planner.getSelectedMigrations(
59
- migrationsByWorkspace
60
- );
61
-
62
- await Runner.run(migrationsToRun, options);
63
- })
64
- );
65
-
66
- cli.strict().parse(argv.slice(2)).argv;
67
- }
68
-
69
- function run(command) {
70
- return async (...args) => {
71
- // checks git status on pwd, returns true if clean / false if not
72
- let isClean = isGitClean.sync();
73
-
74
- console.log('Thanks for trying out @carbon/upgrade! 🙏');
75
- console.log('Checking git status...👀');
76
-
77
- if (!isClean) {
78
- console.error(
79
- 'Git directory is not clean. Please stash or commit your changes.'
80
- );
81
- process.exit(1);
82
- }
83
-
84
- try {
85
- await command(...args);
86
- console.log('Done! ✨');
87
- } catch (error) {
88
- if (error instanceof UpgradeError) {
89
- console.error(error.message);
90
- process.exit(1);
91
- }
92
- console.error('Yikes, looks like something really went wrong.');
93
- console.error('Please make an issue with the following info:');
94
- console.log(error);
95
- process.exit(1);
96
- }
97
- };
98
- }
99
-
100
- module.exports = main;
package/src/error.js DELETED
@@ -1,21 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- class CustomError extends Error {
11
- constructor(message) {
12
- super(message);
13
- this.name = this.constructor.name;
14
- }
15
- }
16
-
17
- class UpgradeError extends CustomError {}
18
-
19
- module.exports = {
20
- UpgradeError,
21
- };
package/src/hash.js DELETED
@@ -1,87 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const BASE62 = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
11
-
12
- /**
13
- * Murmur hash implementation
14
- * @see https://github.com/garycourt/murmurhash-js
15
- * @param {string} str
16
- * @returns {string}
17
- */
18
- function hash(str) {
19
- const length = str.length;
20
- const rem = length & 3;
21
- const len = length ^ rem;
22
-
23
- let h = 0;
24
- let i = 0;
25
- let k;
26
-
27
- while (i !== len) {
28
- const ch4 = str.charCodeAt(i + 3);
29
-
30
- k =
31
- str.charCodeAt(i) ^
32
- (str.charCodeAt(i + 1) << 8) ^
33
- (str.charCodeAt(i + 2) << 16) ^
34
- ((ch4 & 0xff) << 24) ^
35
- ((ch4 & 0xff00) >> 8);
36
-
37
- i += 4;
38
-
39
- k = (k * 0x2d51 + (k & 0xffff) * 0xcc9e0000) >>> 0;
40
- k = (k << 15) | (k >>> 17);
41
- k = (k * 0x3593 + (k & 0xffff) * 0x1b870000) >>> 0;
42
- h ^= k;
43
- h = (h << 13) | (h >>> 19);
44
- h = (h * 5 + 0xe6546b64) >>> 0;
45
- }
46
-
47
- k = 0;
48
- switch (rem) {
49
- /* eslint-disable no-fallthrough */
50
- case 3:
51
- k ^= str.charCodeAt(len + 2) << 16;
52
- case 2:
53
- k ^= str.charCodeAt(len + 1) << 8;
54
- case 1:
55
- k ^= str.charCodeAt(len);
56
-
57
- k = (k * 0x2d51 + (k & 0xffff) * 0xcc9e0000) >>> 0;
58
- k = (k << 15) | (k >>> 17);
59
- k = (k * 0x3593 + (k & 0xffff) * 0x1b870000) >>> 0;
60
- h ^= k;
61
- }
62
-
63
- h ^= length;
64
- h ^= h >>> 16;
65
- h = (h * 0xca6b + (h & 0xffff) * 0x85eb0000) >>> 0;
66
- h ^= h >>> 13;
67
- h = (h * 0xae35 + (h & 0xffff) * 0xc2b20000) >>> 0;
68
- h ^= h >>> 16;
69
-
70
- h >>>= 0;
71
-
72
- if (!h) {
73
- return '0';
74
- }
75
-
76
- let s = '';
77
- while (h) {
78
- const d = h % 62;
79
- s = BASE62[d] + s;
80
- h = (h - d) / 62;
81
- }
82
- return s;
83
- }
84
-
85
- module.exports = {
86
- hash,
87
- };
package/src/migration.js DELETED
@@ -1,85 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const semver = require('semver');
11
- const migrations = require('./migrations');
12
-
13
- const codes = {
14
- // The migration is supported for the current workspace for the matching
15
- // dependency
16
- SUPPORTED: 'supported',
17
- // The migration is supported for the current dependency in the workspace but
18
- // the version range does not intersect
19
- RANGE_MISMATCH: 'range_mismatch',
20
- };
21
-
22
- /**
23
- * Get the currently supported migrations
24
- * @returns {Array<Migration>}
25
- */
26
- function getMigrations() {
27
- return migrations;
28
- }
29
-
30
- function getMigrationsByWorkspace(workspaces, migrations) {
31
- return workspaces
32
- .map((workspace) => {
33
- const { dependencies } = workspace;
34
-
35
- return {
36
- workspace,
37
- migrationOptions: migrations
38
- .filter((migration) => {
39
- return dependencies.find((dependency) => {
40
- return dependency.name === migration.packageName;
41
- });
42
- })
43
- .map((migration) => {
44
- const dependency = dependencies.find((dependency) => {
45
- return dependency.name === migration.packageName;
46
- });
47
-
48
- if (semver.intersects(migration.from, dependency.version)) {
49
- return {
50
- dependency,
51
- migration,
52
- available: true,
53
- code: codes.SUPPORTED,
54
- };
55
- }
56
-
57
- return {
58
- dependency,
59
- migration,
60
- available: false,
61
- code: codes.RANGE_MISMATCH,
62
- };
63
- }),
64
- };
65
- })
66
- .filter((workspace) => {
67
- return workspace.migrationOptions.length > 0;
68
- });
69
- }
70
-
71
- function applyMigrations() {}
72
-
73
- /**
74
- * A module for finding and running migrations
75
- */
76
- const Migration = {
77
- codes,
78
- getMigrations,
79
- getMigrationsByWorkspace,
80
- applyMigrations,
81
- };
82
-
83
- module.exports = {
84
- Migration,
85
- };
@@ -1,41 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const supported = [
11
- {
12
- packageName: 'react',
13
- // the range we would like to migrate *from*
14
- from: '>=16',
15
- // the version we would like to migrate *to*
16
- to: '18.0.0',
17
-
18
- async migrate(workspace) {
19
- console.log(
20
- 'migrate the react package in the %s workspace',
21
- workspace.name
22
- );
23
- },
24
- },
25
- {
26
- packageName: 'react-dom',
27
- // the range we would like to migrate *from*
28
- from: '>=16',
29
- // the version we would like to migrate *to*
30
- to: '18.0.0',
31
-
32
- async migrate(workspace) {
33
- console.log(
34
- 'migrate the react-dom package in the %s workspace',
35
- workspace.name
36
- );
37
- },
38
- },
39
- ];
40
-
41
- module.exports = supported;
package/src/planner.js DELETED
@@ -1,58 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const { prompt } = require('inquirer');
11
-
12
- const Planner = {
13
- /**
14
- * Prompt the user to see which migrations they would like to apply for each
15
- * workspace
16
- * @param {Array<WorkspaceMigration>} migrationsByWorkspace
17
- * @returns {Array<WorkspaceMigration>}
18
- */
19
- async getSelectedMigrations(migrationsByWorkspace) {
20
- const answers = [];
21
-
22
- for (const { workspace, migrationOptions } of migrationsByWorkspace) {
23
- const answer = await prompt({
24
- type: 'checkbox',
25
- message: `Migrations available for ${workspace.name}`,
26
- name: 'selected',
27
- choices: migrationOptions
28
- .filter((migrationOption) => {
29
- return migrationOption.available === true;
30
- })
31
- .map((migrationOption) => {
32
- const { dependency, migration } = migrationOption;
33
- return {
34
- name: `Migrate ${dependency.name} from: ${dependency.version} to: ${migration.to}`,
35
- value: migration,
36
- checked: true,
37
- };
38
- }),
39
- });
40
-
41
- answers.push(answer);
42
- }
43
-
44
- return migrationsByWorkspace.map(({ workspace, migrationOptions }, i) => {
45
- const answer = answers[i];
46
- return {
47
- workspace,
48
- migrationOptions: migrationOptions.filter((migrationOption) => {
49
- return answer.selected.includes(migrationOption.migration);
50
- }),
51
- };
52
- });
53
- },
54
- };
55
-
56
- module.exports = {
57
- Planner,
58
- };
@@ -1,52 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @jest-environment node
8
- */
9
-
10
- 'use strict';
11
-
12
- const { Volume } = require('memfs');
13
-
14
- function setupProject(mockVol) {
15
- jest.mock('fs', () => {
16
- const { createFsFromVolume } = require('memfs');
17
- const fs = createFsFromVolume(mockVol);
18
-
19
- // Our usage of `fs-extra` requires a fs.realpath.native value that memfs
20
- // does not seem to provide.
21
- Object.defineProperty(fs.realpath, 'native', {
22
- value: jest.fn(),
23
- enumerable: true,
24
- writable: false,
25
- });
26
-
27
- return fs;
28
- });
29
- return require('../project').Project;
30
- }
31
-
32
- describe('Project', () => {
33
- afterEach(() => {
34
- jest.resetModules();
35
- });
36
-
37
- it('should detect a project from the current working directory', async () => {
38
- const directory = '/test';
39
- const Project = setupProject(
40
- Volume.fromJSON(
41
- {
42
- './package.json': JSON.stringify({}),
43
- './src/test.js': '',
44
- },
45
- directory
46
- )
47
- );
48
-
49
- const project = await Project.detect('/test/src');
50
- expect(project.directory).toEqual('/test');
51
- });
52
- });
@@ -1,92 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @jest-environment node
8
- */
9
-
10
- 'use strict';
11
-
12
- const { Volume } = require('memfs');
13
-
14
- function setupWorkspace(mockVol) {
15
- jest.mock('fs', () => {
16
- const { createFsFromVolume } = require('memfs');
17
- const fs = createFsFromVolume(mockVol);
18
-
19
- // Our usage of `fs-extra` requires a fs.realpath.native value that memfs
20
- // does not seem to provide.
21
- Object.defineProperty(fs.realpath, 'native', {
22
- value: jest.fn(),
23
- enumerable: true,
24
- writable: false,
25
- });
26
-
27
- return fs;
28
- });
29
- return require('../workspace').Workspace;
30
- }
31
-
32
- describe('Workspace', () => {
33
- afterEach(() => {
34
- jest.resetModules();
35
- });
36
-
37
- it('should load a single directory with a `package.json`', async () => {
38
- const directory = '/test';
39
- const Workspace = setupWorkspace(
40
- Volume.fromJSON(
41
- {
42
- './package.json': JSON.stringify({}),
43
- },
44
- directory
45
- )
46
- );
47
- const workspace = await Workspace.load(directory);
48
-
49
- expect(
50
- Array.from(workspace.getWorkspaces()).map((w) => w.directory)
51
- ).toEqual(['/test']);
52
-
53
- await expect(Workspace.load(directory)).resolves.toBeInstanceOf(Workspace);
54
- });
55
-
56
- it('should load a workspace', async () => {
57
- const directory = '/test';
58
- const Workspace = setupWorkspace(
59
- Volume.fromJSON(
60
- {
61
- './package.json': JSON.stringify({
62
- workspaces: ['packages/*'],
63
- }),
64
- 'packages/a/package.json': JSON.stringify({
65
- version: '0.1.0',
66
- }),
67
- 'packages/b/package.json': JSON.stringify({
68
- dependencies: {
69
- a: '^0.1.0',
70
- },
71
- }),
72
- 'packages/c/package.json': JSON.stringify({
73
- workspaces: ['examples/*'],
74
- }),
75
- 'packages/c/examples/d/package.json': JSON.stringify({}),
76
- },
77
- directory
78
- )
79
- );
80
-
81
- const workspace = await Workspace.load(directory);
82
- expect(
83
- Array.from(workspace.getWorkspaces()).map((w) => w.directory)
84
- ).toEqual([
85
- '/test',
86
- '/test/packages/a',
87
- '/test/packages/b',
88
- '/test/packages/c',
89
- '/test/packages/c/examples/d',
90
- ]);
91
- });
92
- });
@@ -1,16 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2019, 2019
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- const { Project } = require('./project');
11
- const { Workspace } = require('./workspace');
12
-
13
- module.exports = {
14
- Project,
15
- Workspace,
16
- };