Skip to content

Commit

Permalink
feat: add eds-migrate command
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremiah-clothier committed May 23, 2024
1 parent 72daa0b commit b45061e
Show file tree
Hide file tree
Showing 14 changed files with 1,395 additions and 3 deletions.
14 changes: 14 additions & 0 deletions bin/eds-migrate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env node

// eslint-disable-next-line import/extensions
require('../lib/bin/eds-migrate.js')
.run()
.then(() => {
process.exit(0);
})
.catch((error) => {
if (error) {
console.log(error);
}
process.exit(1);
});
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@
"bin": {
"eds-apply-theme": "bin/eds-apply-theme.js",
"eds-import-from-figma": "bin/eds-import-from-figma.js",
"eds-init-theme": "bin/eds-init.js"
"eds-init-theme": "bin/eds-init.js",
"eds-migrate": "bin/eds-migrate.js"
},
"scripts": {
"build": "yarn build:clean && yarn build:tokens && yarn build:js && yarn copy-fonts-to-lib",
"build": "yarn build:clean && yarn build:tokens && yarn build:js && yarn build:bin && yarn copy-fonts-to-lib",
"build:bin": "tsc -p src/bin/tsconfig.json",
"build:clean": "rm -rf lib/",
"build:tokens": "rm -rf src/tokens-dist/ && node ./style-dictionary.config.js && yarn prettier-tokens-dist",
"build:js": "rollup --config",
Expand Down Expand Up @@ -105,6 +107,8 @@
"react-uid": "^2.3.3",
"style-dictionary": "^3.9.2",
"svg4everybody": "^2.1.9",
"ts-dedent": "^2.2.0",
"ts-morph": "^22.0.0",
"yargs": "^17.7.2"
},
"devDependencies": {
Expand Down
44 changes: 44 additions & 0 deletions src/bin/eds-migrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import chalk from 'chalk';
import { hideBin } from 'yargs/helpers'; // eslint-disable-line import/extensions
import yargs from 'yargs/yargs';
import runMigration, { listMigrations } from './migrate';

export async function run() {
// Set up the command
const args = yargs(hideBin(process.argv))
.command(
['$0 [options]'],
'Run an EDS codemod migration on your source files',
)
.options({
list: {
describe: 'List available migrations',
type: 'boolean',
},
name: {
describe: 'The migration to run',
type: 'string',
},
verbose: {
describe: 'Print additional details for debugging purposes',
type: 'boolean',
},
}).argv;

// @ts-expect-error Typing for args isn't as good as we'd like them to be
const { name, list, verbose: isVerbose } = args;

if (list) {
listMigrations().forEach((migration) => {
console.log(` ${migration}`);
});
} else if (name) {
await runMigration(name, { isVerbose });
} else {
console.warn(
chalk.red(
'Migrate: please use --name to specify a migration name or use --list to see the list of available migrations',
),
);
}
}
19 changes: 19 additions & 0 deletions src/bin/migrate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# EDS Migrate

EDS Migrate is a collection of codemods written with [ts-morph](https://ts-morph.com/). It will help you migrate breaking changes & deprecations.

## CLI Integration

The preferred way to run these codemods is via the CLI's `eds-migrate` command.

```
npx eds-migrate --help
```

## Additional Resources

Below are some helpful resources when writing codemodes with ts-morph

- [ts-morph documentation](https://ts-morph.com/)
- [TypeScript AST Viewer](https://ts-ast-viewer.com/#)
- [AST Explorer](https://astexplorer.net/)
27 changes: 27 additions & 0 deletions src/bin/migrate/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
InMemoryFileSystemHost,
Project,
type ImportDeclaration,
} from 'ts-morph';

/**
* Checks if the import declaration is for the design system.
* @returns {boolean} - True if the import is from the design system, false otherwise.
*/
export function isDesignSystemImport(node: ImportDeclaration) {
return node.getModuleSpecifierValue() === '@chanzuckerberg/eds';
}

/**
* Creates an in-memory source file for testing
*/
export function createTestSourceFile(sourceFileText: string) {
const host = new InMemoryFileSystemHost();
const project = new Project({
compilerOptions: undefined,
fileSystem: host,
skipLoadingLibFiles: true,
});

return project.createSourceFile('testFile.tsx', sourceFileText);
}
52 changes: 52 additions & 0 deletions src/bin/migrate/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import fs from 'node:fs';
import path from 'node:path';
import { Project } from 'ts-morph';

const MIGRATION_DIR = `${__dirname}/migrations`;

/**
* Lists all the available migrations.
*
* @returns {string[]} Array of migration names.
*/
export function listMigrations() {
return fs
.readdirSync(MIGRATION_DIR)
.filter((fname) => fname.endsWith('.js'))
.map((fname) => fname.slice(0, -3));
}

/**
* Runs the migration specified by name with given options.
*
* @param {string} name - The name of the migration.
* @param {Options} options - Options for the migration.
* @returns {Promise<void>} A Promise that resolves when the migration is complete.
*/
export default async function runMigration(
name: string,
options: { isVerbose?: boolean },
): Promise<void> {
const { isVerbose } = options;

// runMigration is called by a CLI we want the directory
// the command is ran in and not the directory of this file
const tsconfigPath = path.join(process.cwd(), './tsconfig.json');
if (isVerbose) {
console.log(`Using the following tsconfig.json file: ${tsconfigPath}`);
}
const project = new Project({
tsConfigFilePath: path.join(tsconfigPath),
});

const pathToMigration = path.join(MIGRATION_DIR, `${name}.js`);
try {
console.log(`Running the following migration: "${name}"`);
const { default: migration } = await import(pathToMigration);

Check failure on line 45 in src/bin/migrate/index.ts

View workflow job for this annotation

GitHub Actions / test

Dynamic imports are only supported when the '--module' flag is set to 'es2020', 'es2022', 'esnext', 'commonjs', 'amd', 'system', 'umd', 'node16', or 'nodenext'.
migration(project);
} catch (error) {
console.error('Error importing module:', error);
}

await project.save();
}
Loading

0 comments on commit b45061e

Please sign in to comment.