@sproutsocial/seeds-codemod-cli
v0.5.0
Published
CLI tool for running Seeds design system codemods
Readme
@sproutsocial/seeds-codemod-cli
CLI tool for running Seeds design system codemods.
Installation
npm install --save-dev @sproutsocial/seeds-codemod-cli
# or
yarn add --dev @sproutsocial/seeds-codemod-cliThat's it! The CLI includes everything it needs (including jscodeshift).
Usage
Interactive Mode (Recommended)
Run without arguments to enter interactive mode:
npx seeds-codemodYou'll be prompted to select a codemod, specify the target path, and configure options.
Direct Mode
Run a specific codemod directly:
npx seeds-codemod <codemod-name> <path> [options]Example:
npx seeds-codemod modal-v1-to-v2 ./src --parser=tsx --dry-runCommands
list
List all available codemods:
npx seeds-codemod listinfo <codemod>
Show detailed information about a specific codemod:
npx seeds-codemod info modal-v1-to-v2Options
--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)
vertical-bar-chart-v1-to-v2
Migrates the legacy VerticalBarChart (root export of @sproutsocial/seeds-react-data-viz)
to the v2 per-family bar component on the /bar subpath. The v2 component keeps the
VerticalBarChart name — only the import path and prop shapes change. Handles:
- Import path:
@sproutsocial/seeds-react-data-viz->@sproutsocial/seeds-react-data-viz/bar(splitsVerticalBarChartonto/barwhen other symbols share the root import; preserves aliases) - Data restructure:
data={[{ name, points: [{ x, y }] }]}->series={[{ name, data: [y], color? }]}plusxAxis={{ categories: [x] }}, for the common category-axis case (static array literal, stringx, every series sharing the same orderedxset).styles.colormoves toseries[i].color. - Number/locale formatting: folds
numberFormat/currency/numberLocale/textLocaleinto a single declarativeyAxis={{ format: { ... } }}(ValueFormat) - Injects the v2-required accessibility
descriptionprop (placeholder, flagged) onClick: aliases the destructuredxarg toposition(({ x }) => …->({ position: x }) => …)xAnnotations: converts a static keyed map to a v2annotations={[{ position }]}array- Passes
tooltip,invalidNumberLabel,tooltipClickLabelthrough unchanged - Emits
CLAUDE-TODOblock comments for everything it cannot mechanically convert: non-literal / datetime / mismatcheddata,styles.pattern, per-seriesicon,seriesLimit,showSeriesLimitWarning,tooltipDateFormatter,xAxisLabelFormatter,yAxisLabelFormatter,timeFormat, and theannotationsmarker/details render-props. (timeFormatmaps toxAxis.timeFormaton atype: "datetime"axis, but the codemod flags it rather than building the datetime axis — the[timestamp, value]data reshape is manual.)
Returns a no-op (null) for files without a v1 VerticalBarChart import, so it is safe and
idempotent to run repo-wide. See src/usage-patterns/VERTICALBARCHARTV1_PATTERNS.md for the
file-by-file migration guidance this codemod automates.
Local Development
Prerequisites
- Node.js >= 18
- yarn (workspace manager)
Setup
From the monorepo root:
# Install dependencies
yarn install
# Build the CLI
cd seeds-tooling/seeds-codemod-cli
yarn buildRunning Locally
You can test the CLI locally in two ways:
1. Using the built CLI directly
# 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-run2. Using npm link
# 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-cliDevelopment Workflow
# Watch mode - rebuilds on file changes
yarn dev
# In another terminal, test your changes
node dist/index.js <command>Testing
Running Tests
# Run all tests
yarn test
# Watch mode for development
yarn test:watch
# Type checking
yarn typecheckTest Structure
Tests are located in __tests__/:
__tests__/
codemods/
modal-v1-to-v2.test.ts # Codemod transformation tests
fixtures/
modal-v1-input.tsx # Sample input files for testingWriting Codemod Tests
Codemod tests use jscodeshift directly to verify transformations:
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/:
// 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/:
// __tests__/codemods/my-codemod.test.ts
import jscodeshift from "jscodeshift";
import transform from "../../src/codemods/my-codemod";
// ... test cases3. Build and Test
# 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-runCodemod Best Practices
Always return
nullif no changes were made - This prevents unnecessary file rewritesExport metadata - The CLI uses metadata for
listandinfocommandsUse descriptive tags - Helps users discover relevant codemods
Test edge cases - Include tests for:
- No-op cases (files that shouldn't change)
- Different import patterns
- All prop/component variations
Be conservative - It's better to leave code unchanged than to introduce bugs
Add comments for manual review items - If a transformation can't be done automatically, leave a TODO comment
jscodeshift Resources
- jscodeshift Documentation
- AST Explorer - Use "typescript" parser and "jscodeshift" transform
- 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 to transform your code.
Discovery
The CLI discovers codemods from:
- node_modules - When installed as a dependency
- Workspace - When developing in the Seeds monorepo
Codemods are identified by their metadata export which includes name, description, and tags.
License
MIT
