npm package: @sproutsocial/seeds-codemod-cli
Description: CLI tool for running Seeds design system codemods
Author: Sprout Social, Inc.
Latest version: 0.3.0

# @sproutsocial/seeds-codemod-cli

CLI tool for running Seeds design system codemods.

## Installation

```bash
npm install --save-dev @sproutsocial/seeds-codemod-cli
# or
yarn add --dev @sproutsocial/seeds-codemod-cli
```

That's it! The CLI includes everything it needs (including jscodeshift).

## Usage

### Interactive Mode (Recommended)

Run without arguments to enter interactive mode:

```bash
npx seeds-codemod
```

You'll be prompted to select a codemod, specify the target path, and configure options.

### Direct Mode

Run a specific codemod directly:

```bash
npx seeds-codemod <codemod-name> <path> [options]
```

**Example:**

```bash
npx seeds-codemod modal-v1-to-v2 ./src --parser=tsx --dry-run
```

### Commands

#### `list`

List all available codemods:

```bash
npx seeds-codemod list
```

#### `info <codemod>`

Show detailed information about a specific codemod:

```bash
npx seeds-codemod info modal-v1-to-v2
```

### Options

- `--dry-run` - Preview changes without writing (default: false)
- `--parser <parser>` - Parser to use: tsx, ts, babel, flow (default: tsx)
- `--quote <style>` - Quote style: single, double (default: single)
- `--verbose` - Show detailed output
- `--no-cache` - Skip discovery cache

## Available Codemods

### `modal-v1-to-v2`

Migrates Modal v1 to Modal v2 API. Handles:

- Import path changes (`@sproutsocial/racine` -> `@sproutsocial/racine/modal/v2`)
- Prop renames: `isOpen` -> `open`, `label` -> `aria-label`, `closeButtonLabel` -> `closeButtonAriaLabel`
- Sub-component transformations: `Modal.Header` -> `ModalHeader`, `Modal.Content` -> `ModalBody`, `Modal.Footer` -> `ModalCustomFooter`
- Removes unsupported props: `width`, `appElementSelector`, `bordered` (on ModalHeader)
- Removes `Modal.CloseButton` (v2 handles close button automatically)

## Local Development

### Prerequisites

- Node.js >= 18
- yarn (workspace manager)

### Setup

From the monorepo root:

```bash
# Install dependencies
yarn install

# Build the CLI
cd seeds-tooling/seeds-codemod-cli
yarn build
```

### Running Locally

You can test the CLI locally in two ways:

#### 1. Using the built CLI directly

```bash
# Build first
yarn build

# Run the CLI from dist
node dist/index.js list
node dist/index.js modal-v1-to-v2 ./path/to/test --dry-run
```

#### 2. Using npm link

```bash
# From seeds-codemod-cli directory
npm link

# Now you can use it anywhere
seeds-codemod list
seeds-codemod modal-v1-to-v2 ./src --dry-run

# Unlink when done
npm unlink -g @sproutsocial/seeds-codemod-cli
```

### Development Workflow

```bash
# Watch mode - rebuilds on file changes
yarn dev

# In another terminal, test your changes
node dist/index.js <command>
```

## Testing

### Running Tests

```bash
# Run all tests
yarn test

# Watch mode for development
yarn test:watch

# Type checking
yarn typecheck
```

### Test Structure

Tests are located in `__tests__/`:

```text
__tests__/
  codemods/
    modal-v1-to-v2.test.ts    # Codemod transformation tests
  fixtures/
    modal-v1-input.tsx        # Sample input files for testing
```

### Writing Codemod Tests

Codemod tests use jscodeshift directly to verify transformations:

```typescript
import jscodeshift from "jscodeshift";
import transform from "../../src/codemods/your-codemod";

function runTransform(source: string): string | null {
  const fileInfo = { path: "test.tsx", source };
  const api = {
    jscodeshift: jscodeshift.withParser("tsx"),
    j: jscodeshift.withParser("tsx"),
    stats: () => {},
    report: () => {},
  };
  return transform(fileInfo, api, {});
}

describe("your-codemod", () => {
  it("transforms X to Y", () => {
    const input = `import { Old } from 'package';`;
    const output = runTransform(input);
    expect(output).toContain("New");
  });
});
```

## Adding New Codemods

### 1. Create the Codemod File

Create a new file in `src/codemods/`:

```typescript
// src/codemods/my-codemod.ts
import type { Transform, API, FileInfo, Options } from "jscodeshift";

// Metadata for CLI discovery
export const metadata = {
  name: "my-codemod",
  version: "1.0.0",
  description: "Description of what this codemod does",
  tags: ["component-name", "migration"],
  example: "npx seeds-codemod my-codemod ./src",
};

const transform: Transform = (file: FileInfo, api: API, options: Options) => {
  const j = api.jscodeshift;
  const root = j(file.source);
  let hasModifications = false;

  // Your transformation logic here
  // Use root.find(), forEach(), replaceWith(), etc.

  // Return modified source or null if no changes
  return hasModifications ? root.toSource() : null;
};

export default transform;
```

### 2. Add Tests

Create a test file in `__tests__/codemods/`:

```typescript
// __tests__/codemods/my-codemod.test.ts
import jscodeshift from "jscodeshift";
import transform from "../../src/codemods/my-codemod";

// ... test cases
```

### 3. Build and Test

```bash
# Build
yarn build

# Run tests
yarn test

# Test the codemod locally
node dist/index.js list  # Verify it appears
node dist/index.js my-codemod ./test-file.tsx --dry-run
```

### Codemod Best Practices

1. **Always return `null` if no changes were made** - This prevents unnecessary file rewrites

2. **Export metadata** - The CLI uses metadata for `list` and `info` commands

3. **Use descriptive tags** - Helps users discover relevant codemods

4. **Test edge cases** - Include tests for:
   - No-op cases (files that shouldn't change)
   - Different import patterns
   - All prop/component variations

5. **Be conservative** - It's better to leave code unchanged than to introduce bugs

6. **Add comments for manual review items** - If a transformation can't be done automatically, leave a TODO comment

### jscodeshift Resources

- [jscodeshift Documentation](https://github.com/facebook/jscodeshift)
- [AST Explorer](https://astexplorer.net/) - Use "typescript" parser and "jscodeshift" transform
- [jscodeshift Recipes](https://github.com/facebook/jscodeshift/wiki/jscodeshift-Recipes)

## How It Works

The CLI bundles all codemods internally. When you install `@sproutsocial/seeds-codemod-cli`, you get:

- The CLI tool
- All available codemods
- jscodeshift (no additional dependencies needed!)

Codemods are JavaScript files that use [jscodeshift](https://github.com/facebook/jscodeshift) to transform your code.

### Discovery

The CLI discovers codemods from:

1. **node_modules** - When installed as a dependency
2. **Workspace** - When developing in the Seeds monorepo

Codemods are identified by their `metadata` export which includes name, description, and tags.

## License

MIT